<?php


namespace common\service;


use common\exception\LogicException;
use common\model\EntityModel;
use common\model\MediaModel;
use common\model\ModuleModel;
use common\model\NoteModel;
use common\model\OrderModel;
use common\model\OrderTaskListModel;
use common\model\PlaylistItemModel;
use common\model\PlaylistItemVersionModel;
use common\model\PlaylistModel;
use common\model\PlaylistPackageItemModel;
use common\model\PlaylistPackageModel;
use common\model\PlaylistVersionModel;
use common\model\ProjectModel;
use common\model\ReviewRequestModel;
use common\model\ReviewRequestNodeModel;
use common\model\ReviewWorkflowModel;
use common\model\StatusModel;
use common\model\StepCategoryModel;
use common\model\StepModel;
use common\model\TaskClockModel;
use common\model\TaskModel;
use common\model\TaskWorkOrderModel;
use common\model\UserModel;
use common\model\VersionCheckListModel;
use common\model\VersionModel;
use support\EntityTaskFilterParser;
use support\ErrorCode;
use support\SingletonTrait;
use think\Exception;
use think\module\Module;
use Throwable;
use Webman\Stomp\Client;

class ReviewTaskService
{

    /** @var TaskModel */
    private $taskModel;

    /** @var EntityModel */
    private $entityModel;

    /** @var VersionModel */
    private $versionModel;

    /** @var PlaylistModel */
    private $playlistModel;

    /** @var PlaylistItemModel */
    private $playlistItemModel;
    private $playlistItemVersionModel;
    private $reviewRequestNodeModel;
    private $playlistVersionModel;
    private $reviewRequestModel;
    private $mediaModel;
    private $stepModel;
    private $playlistPackageModel;
    private $playlistPackageItemModel;
    private $stepCategoryModel;
	private  $moduleModel;

    use EntityTaskFilterParser;
    // 单例工具
    use SingletonTrait;

    public function __construct()
    {
        $this->taskModel = model(TaskModel::class);
        $this->entityModel = model(EntityModel::class);
        $this->versionModel = model(VersionModel::class);
        $this->playlistPackageModel = model(PlaylistPackageModel::class);
        $this->playlistPackageItemModel = model(PlaylistPackageItemModel::class);
        $this->playlistModel = model(PlaylistModel::class);
        $this->playlistItemModel = model(PlaylistItemModel::class);
        $this->playlistItemVersionModel = model(PlaylistItemVersionModel::class);
        $this->reviewRequestNodeModel = model(ReviewRequestNodeModel::class);
        $this->reviewRequestModel = model(ReviewRequestModel::class);
        $this->playlistVersionModel = model(PlaylistVersionModel::class);
        $this->mediaModel = model(MediaModel::class);
        $this->stepModel = model(StepModel::class);
        $this->stepCategoryModel = model(StepCategoryModel::class);
		$this->moduleModel = model(Module::class);
    }

    public function getCheckRoleCode()
    {
        return TaskService::HEADMAN_CODE;
    }

    /**
     * 查询分类下需要进行checkRole之后操作的工序
     * @param $stepCategoryIdList
     * @return array
     */
    public function getStepCategoryNeedCheckRoleStepList($stepCategoryIdList)
    {
        if (empty($stepCategoryIdList)) {
            return [];
        }
        $stepList = $this->stepModel
            ->join("step_review_workflow_relation on step_review_workflow_relation.step_id = step.id")
            ->join('review_workflow on step_review_workflow_relation.review_workflow_id = review_workflow.id')
            ->field("step.id,step.name,step.code,step.step_category_id,step.show_index,json_extract(review_workflow.config,'$.nodes.reviewer') as reviewer_data")
            ->where([
                'step.step_category_id' => ['IN', $stepCategoryIdList]
            ])
            ->select();
        $matchStepList = [];
        $matchReviewRoleCode = $this->getCheckRoleCode();
        foreach ($stepList as $step) {
            $reviewers = json_decode($step['reviewer_data'], true);
            $isMatch = false;
            $reviewersCount = count($reviewers);
            foreach ($reviewers as $index => $reviewer) {
                if ($reviewer['role'] === $matchReviewRoleCode && $index != $reviewersCount - 1) {
                    // 包含组长节点 并且不是最后一个审核节点
                    $isMatch = true;
                }
            }
            if ($isMatch) {
                unset($step['reviewer_data']);
                $matchStepList[$step['id']] = $step;
            }
        }
        return $matchStepList;
    }

    /**
     * 播放列表分类数据
     * @param string $moduleCode
     * @param int $projectId
     * @param int $episodeId
     * @param $dateSource
     * @param $isNormalCategory
     * @param int $userId
     * @return array
     */
    public function getPlayListStepCategoryData(string $moduleCode, int $projectId, int $episodeId, $dateSource, $isNormalCategory, int $userId)
    {
        $stepCategoryList = StepService::getInstance()->getStepCategoryByMergeModuleConfig($moduleCode, false);
        if (empty($stepCategoryList)) {
            return [];
        }
        $res = array_column($stepCategoryList, null, 'id');
        foreach ($res as &$i) {
            $i['data_source_count'] = 0;
        }

        $stepCategoryListIds = array_column($stepCategoryList, 'id', 'id');

        if (count($stepCategoryListIds) === 0) {
            return [];
        }
        $statusList = array_column(model(StatusModel::class)->field('id,code')->select(), 'id', 'code');
        $stepCount = [];
        if ($isNormalCategory !== 'yes') {
            $matchStepList = $this->getStepCategoryNeedCheckRoleStepList($stepCategoryListIds);
            $episode = model(EntityModel::class)->find($episodeId);
            if (empty($episode)) {
                throw new LogicException('episode not found', ErrorCode::MISSING_EPISODE);
            }
            switch ($dateSource) {
                case 'assemble_count':
                    $countFilter = [
                        'entity.initial_episode_code' => $episode['code'],
                        'entity.project_id' => $projectId,
                        'task.step_id' => ['IN', implode(',', array_keys($matchStepList))],
                        "JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))" => ['NEQ', $statusList['closed']]
                    ];
                    $stepCount = model(TaskModel::class)
                        ->join('entity on entity.id = task.entity_id')
                        ->join('module on module.id = entity.module_id')
                        ->where($countFilter)
                        ->field('count(*) as count,task.step_id')
                        ->group('task.step_id')
                        ->select();
                    $stepCount = array_column($stepCount, 'count', 'step_id');
                    break;
                case 'wait_submit_playlist_count':
                    $taskModuleId = Module::$moduleDictData['module_index_by_code']['task']['id'];
                    $versionModuleId = Module::$moduleDictData['module_index_by_code']['version']['id'];

                    $countFilter = [
                        'e.project_id' => $projectId,
                        'e.initial_episode_code' => $episode['code'],
                        'rr.is_reviewed' => 'no',
                        'rr.need_handle' => 'yes',
                        'v.is_second_submit' => 'no',
                        't.step_id' => ['IN', array_keys($matchStepList)],
                        "JSON_UNQUOTE(JSON_EXTRACT(e.json, CONCAT('$.', module.code, '_status')))" => ['NEQ', $statusList['closed']]
                    ];
                    $stepCountRes = [];
                    if ($moduleCode === 'asset') {
                        // 统计概念分类数据
                        $designCount = model(PlaylistPackageItemModel::class)
                            ->alias('ppi')
                            ->join('entity e ON e.id = ppi.entity_id')
                            ->join('task t ON t.entity_id = e.id AND t.step_type=\'step\'')
                            ->join('version v ON v.link_id = t.id AND v.module_id = ' . $taskModuleId)
                            ->join('review_request rr ON rr.link_id = v.id AND rr.module_id = ' . $versionModuleId)
                            ->join('module on module.id = e.module_id')
                            ->where($countFilter)
                            ->field('count(DISTINCT ppi.playlist_package_id) as count,t.step_id')
                            ->group('t.step_id')
                            ->select();
                        $stepCountRes = $designCount;
                        // 资产分类数据统计
                        $assetStepCount = model(PlaylistPackageItemModel::class)
                            ->alias('ppi')
                            ->join("entity e ON   ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(e.json,'$.asset_design'))")
                            ->join('task t ON t.entity_id = e.id AND t.step_type=\'step\'')
                            ->join('version v ON v.link_id = t.id AND v.module_id = ' . $taskModuleId)
                            ->join('review_request rr ON rr.link_id = v.id AND rr.module_id = ' . $versionModuleId)
                            ->join('module on module.id = e.module_id')
                            ->where($countFilter)
                            ->field('count(DISTINCT ppi.playlist_package_id) as count,t.step_id')
                            ->group('t.step_id')
                            ->select();
                        $stepCountRes = array_merge($stepCountRes, $assetStepCount);
                        // 关卡分类数据统计
                        $levelStepCount = model(PlaylistPackageItemModel::class)
                            ->alias('ppi')
                            ->join("entity e ON   ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(e.json,'$.level_design'))")
                            ->join('task t ON t.entity_id = e.id AND t.step_type=\'step\'')
                            ->join('version v ON v.link_id = t.id AND v.module_id = ' . $taskModuleId)
                            ->join('review_request rr ON rr.link_id = v.id AND rr.module_id = ' . $versionModuleId)
                            ->join('module on module.id = e.module_id')
                            ->where($countFilter)
                            ->field('count(DISTINCT ppi.playlist_package_id) as count,t.step_id')
                            ->group('t.step_id')
                            ->select();
                        $stepCountRes = array_merge($stepCountRes, $levelStepCount);

                    } else {
                        // 统计镜头分类数据
                        $stepCount = model(PlaylistPackageItemModel::class)
                            ->alias('ppi')
                            ->join("entity e ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(e.json,'$.shot_storyboard'))")
                            ->join('task t ON t.entity_id = e.id AND t.step_type=\'step\'')
                            ->join('version v ON v.link_id = t.id AND v.module_id = ' . $taskModuleId)
                            ->join('review_request rr ON rr.link_id = v.id AND rr.module_id = ' . $versionModuleId)
                            ->join('module on module.id = e.module_id')
                            ->where($countFilter)
                            ->field('count(DISTINCT ppi.playlist_package_id) as count,t.step_id')
                            ->group('t.step_id')
                            ->select();
                        $stepCountRes = $stepCount;
                        // 序列分类数据统计
                        $shotModuleId = Module::$moduleDictData['module_index_by_code']['shot']['id'];
                        $sequenceModuleId = Module::$moduleDictData['module_index_by_code']['sequence']['id'];
                        $assetStepCount = model(PlaylistPackageItemModel::class)
                            ->alias('ppi')
                            ->join("INNER JOIN (select * from entity where module_id = $shotModuleId and project_id = $projectId and initial_episode_code = '{$episode['code']}') as shot ON ppi.entity_id =  JSON_UNQUOTE(JSON_EXTRACT(shot.json,'$.shot_storyboard'))")
                            ->join("INNER JOIN (select * from entity where module_id = $sequenceModuleId and project_id = $projectId and initial_episode_code = '{$episode['code']}') as e ON shot.entity_id = e.id") //sequence
                            ->join("task t ON t.entity_id = e.id AND t.step_type='step'")
                            ->join('version v ON v.link_id = t.id AND v.module_id = ' . $taskModuleId)
                            ->join('review_request rr ON rr.link_id = v.id AND rr.module_id = ' . $versionModuleId)
                            ->join('module on module.id = e.module_id')
                            ->where($countFilter)
                            ->field('count(DISTINCT ppi.playlist_package_id) as count,t.step_id')
                            ->group('t.step_id')
                            ->select();
                        $stepCountRes = array_merge($stepCountRes, $assetStepCount);
                    }
                    $stepCount = [];
                    foreach ($stepCountRes as $item) {
                        if (!isset($stepCount[$item['step_id']])) {
                            $stepCount[$item['step_id']] = 0;
                        }
                        $stepCount[$item['step_id']] = $item['count'];
                    }
                    break;
                case 'wait_submit_playlist_version_count':
                    $roleCode = $this->getRoleCodeList($userId);
                    $stepCount = [];
                    if (count($roleCode)) {
                        $stepCount = model(PlaylistVersionModel::class)
                            ->where(['project_id' => $projectId, 'initial_episode_code' => $episode['code']])
                            ->where(['current_review_code' => ['IN', $roleCode]])
                            ->field('count(*) as count,step_id')
                            ->group('step_id')
                            ->select();
                    }

                    $stepCount = array_column($stepCount, 'count', 'step_id');
                    break;
            }
        } else {
            $matchStepList = model(StepModel::class)->where([
                'step_category_id' => ['IN', $stepCategoryListIds]
            ])->select();
            $matchStepList = array_column($matchStepList, null, 'id');
        }

        foreach ($matchStepList as &$step) {
            $step['data_source_count'] = $stepCount[$step['id']] ?? 0;
            $res[$step['step_category_id']]['children'][] = $step;
            if (!isset($res[$step['step_category_id']]['data_source_count'])) {
                $res[$step['step_category_id']]['data_source_count'] = 0;
            }
            $res[$step['step_category_id']]['data_source_count'] += $step['data_source_count'];
        }


        return array_values($res);
    }

    /**
     * 审核任务 待组装列表查询
     * @param $tenantId
     * @param $filter
     * @param $page
     * @return array
     */
    public function waitAssembleDesignList($tenantId, $filter, $page)
    {
        $filter['tenant_id'] = $tenantId;
        $filter['module_id'] = Module::$moduleDictData['module_index_by_code']['design']['id'];
        $publishedStatus = StatusService::getInstance()->getOne(['code' => 'task_generated'], 'id,name,code');
        $filter['design_status'] = $publishedStatus['id'];
        $filter = parse_filter_to_tp_where($filter, 'design');
        $entityQueryFields = ['id', 'name', 'code', "initial_episode_code", 'showings_number', 'json'];
        $count = $this->entityModel->alias('design')->field($entityQueryFields)->where($filter)->count();
        $data = $this->entityModel->alias('design')->field($entityQueryFields)->where($filter)->page(...$page)->select();
        foreach ($data as &$item) {
            $item = CommonService::appendJsonFields($item, 'json');
            $item['entity_id_list'][] = $item['id'];
        }
        return ['total' => $count, 'rows' => $data];
    }

    /**
     * 组装播放列表
     * @param int $getTenantId
     * @param int $userId
     * @param string $playListName
     * @param array $entityIdList
     * @param string $moduleCode
     * @param int $createType
     * @param int $orderId
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function assemblePlayList(int $getTenantId, int $userId, string $playListName, array $entityIdList, $moduleCode, $createType = 'assemble_list', $orderId = 0)
    {
        $entityFilter = [
            'tenant_id' => $getTenantId,
            'id' => ['IN', implode(',', $entityIdList)],
        ];
        $entityQueryFields = [
            'id', 'project_id', 'initial_episode_code', 'showings_number'
        ];
        $entityList = $this->entityModel->where($entityFilter)->field($entityQueryFields)->select();
        if (empty($entityList)) {
            throw new LogicException("entity not found", ErrorCode::ENTITY_NOT_FOUND);
        }
        $showingsNumberList = array_column($entityList, 'showings_number');
        $showingsNumberList = array_unique($showingsNumberList);
        $showingsNumberList = array_filter($showingsNumberList, function ($item) {
            return !empty($item);
        });

        $firstEntity = $entityList[0];
        $playListPackageData = [
            'name' => $playListName,
            'tenant_id' => $getTenantId,
            'project_id' => $firstEntity['project_id'],
            'created_by' => $userId,
            'initial_episode_code' => $firstEntity['initial_episode_code'],
            'showings_number_str' => implode(',', $showingsNumberList),
            'module_code' => $moduleCode,
            'create_type' => $createType,
            'order_id' => $orderId,
        ];
        $playListPackageItemData = [];
        foreach ($entityList as $index => $entity) {
            $playListPackageItemData[] = [
                'playlist_package_id' => 0,
                'entity_id' => $entity['id'],
                'sort_index' => $index,
                'created' => time(),
                'created_by' => $userId,
            ];
        }
        $this->playlistPackageModel->startTrans();
        try {
            $res['playlist_package'] = $this->playlistPackageModel->addItem($playListPackageData);
            if ($res['playlist_package'] === false) {
                throw new LogicException($this->playlistPackageModel->getError(), $this->playlistPackageModel->getErrorCode());
            }
            $playListPackageItemData = array_map(function ($item) use ($res) {
                $item['playlist_package_id'] = $res['playlist_package']['id'];
                return $item;
            }, $playListPackageItemData);
            $res['playlist_package_item'] = $this->playlistPackageItemModel->addAll($playListPackageItemData);
            $this->playlistPackageModel->commit();
            return $res;
        } catch (Throwable $e) {
            $this->playlistPackageModel->rollback();
            throw $e;
        }
    }

    /**
     * 已组装播放列表
     * @param $filter
     * @param $page
     * @param $order
     * @return array
     */
    public function assembledAssetList($filter, $page, $order = 'playlist_package.id DESC')
    {
        $res = [
            'total' => 0,
            'rows' => [],
        ];
        $projectId = $filter['project_id'];
        $stepId = $filter['step_id'];
        $stepCategoryId = $filter['step_category_id'];
        $episodeCode = $filter['initial_episode_code'];
        $showingsNumberList = $filter['showings_number_list'] ?? [];
        $nameSearch = $filter['name'] ?? null;
        $planEndTime = $filter['plan_end_time'] ?? [];
        $playlistPackageFilter = [
            'playlist_package.project_id' => $projectId,
            'playlist_package.module_code' => 'asset',
            'playlist_package.initial_episode_code' => $episodeCode,
//            'playlist_package.created_by' => $userId,
//            'task.step_id' => $stepId,
        ];
        if (!empty($nameSearch)) {
            $playlistPackageFilter['playlist_package.name'] = $nameSearch;
        }
        if (!empty($planEndTime)) {
            $playlistPackageFilter['playlist_package.plan_end_time'] = $planEndTime;
        }

        if (!empty($showingsNumberList)) {
            $playlistPackageFilter['_string'] = '';
            $findInSetFilter = [];
            foreach ($showingsNumberList as $showingsNumber) {
                $findInSetFilter[] = 'FIND_IN_SET(\'' . $showingsNumber . '\', playlist_package.showings_number_str)';
            }
            $playlistPackageFilter['_string'] = implode('OR', $findInSetFilter);
        }

        // 判断当前要查询的实体是什么类型
        $stepCategory = $this->stepCategoryModel->find($stepCategoryId);
        if (empty($stepCategory)) {
            throw new LogicException('second level category not found', ErrorCode::STEP_CATEGORY_NOT_FOUND);
        }
        $topStepCategory = $this->stepCategoryModel->find($stepCategory['parent_id']);
        if (empty($topStepCategory)) {
            throw new LogicException('top category not found', ErrorCode::STEP_CATEGORY_NOT_FOUND);
        }
        $currentRealModule = Module::$moduleDictData['module_index_by_id'][$topStepCategory['entity_id']] ?? null;
        if (empty($currentRealModule)) {
            throw new LogicException('current module not found', ErrorCode::MODULE_DOES_NOT_EXIST);
        }

//        $playlistPackageCountQuery = $this->playlistPackageModel
//            ->join('playlist_package_item ppi ON ppi.playlist_package_id = playlist_package.id');
//
//        switch ($currentRealModule['code']) {
//            case 'level':
//            case 'asset':
//                $playlistPackageCountQuery
//                    ->join("entity ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(entity.json,'$.{$currentRealModule['code']}_design'))");
//                break;
//            case 'design':
//                $playlistPackageCountQuery
//                    ->join("entity ON ppi.entity_id = entity.id");
//        }

//        $res['total'] = $this->playlistPackageModel->query("select count(*) as count from " . $playlistPackageCountQuery->join('task on task.entity_id = entity.id')
//                ->where($playlistPackageFilter)
//                ->order($order)->field('playlist_package.id')->group('playlist_package.id')->buildSql() . ' sub_count_query');
//        $res['total'] = intval($res['total'][0]['count']);
//

        $res['total'] = $this->playlistPackageModel->where($playlistPackageFilter)->count();
        if ($res['total'] === 0) {
            return $res;
        }
        // 链表查询分页 保证查询出来的数据有任务
//        $playlistPackageQuery = $this->playlistPackageModel
//            ->join('playlist_package_item ppi ON ppi.playlist_package_id = playlist_package.id')
//            ->where($playlistPackageFilter)
//            ->order($order)->field('playlist_package.id')->group('playlist_package.id')
//            ->page(...$page);
//
//        switch ($currentRealModule['code']) {
//            case 'level':
//            case 'asset':
//                $playlistPackageQuery
//                    ->join("entity ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(entity.json,'$.{$currentRealModule['code']}_design'))");
//                break;
//            case 'design':
//                $playlistPackageQuery
//                    ->join("entity ON ppi.entity_id = entity.id");
//        }
//        $playlistPackageIdList = $playlistPackageQuery->join('task on task.entity_id = entity.id')->select();
//        $playlistPackageList = $this->playlistPackageModel
//            ->where(['id' => ['IN', array_column($playlistPackageIdList, 'id')]])
//            ->order($order)
//            ->select();

        $playlistPackageList = $this->playlistPackageModel
            ->where($playlistPackageFilter)
            ->order($order)
            ->page(...$page)
            ->select();

        if (count($playlistPackageList) === 0) {
            return $res;
        }
        $playlistPackageIdList = array_column($playlistPackageList, 'id');

        $playlistFilter = [
            'playlist_package_id' => ['IN', $playlistPackageIdList],
            'initial_episode_code' => $episodeCode,
            'step_category_id' => $stepCategoryId,
            'step_id' => $stepId,
        ];
        $playlistList = $this->playlistModel->where($playlistFilter)->select();
        $playlistList = array_column($playlistList, null, 'playlist_package_id');

        $playlistVersionFilter = [
            'playlist_package_id' => ['IN', $playlistPackageIdList],
            'initial_episode_code' => $episodeCode,
            'step_category_id' => $stepCategoryId,
            'step_id' => $stepId,
        ];

        $maxPlaylistVersionList = $this->playlistVersionModel
            ->where($playlistVersionFilter)
            ->field('max(id) id')
            ->group('playlist_package_id')
            ->select();
        $maxPlaylistVersionIdList = array_column($maxPlaylistVersionList, 'id');
        $playlistVersionList = [];
        $playlistVersionItemList = [];
        if (count($maxPlaylistVersionIdList) > 0) {
            $playlistVersionList = $this->playlistVersionModel->where(['id' => ['IN', $maxPlaylistVersionIdList]])->select();
            $playlistVersionItemList = $this->playlistItemVersionModel
                ->where(['playlist_version_id' => ['IN', $maxPlaylistVersionIdList]])
                ->select();
        }

        $taskDataListFilter = [
            "ppi.playlist_package_id" => ['IN', $playlistPackageIdList],
            'task.step_type' => 'step',
            'task.step_category_id' => $stepCategoryId,
            'task.step_id' => $stepId,
        ];
        $taskDataListQuery = $this->taskModel
            ->join('entity on entity.id = task.entity_id and module_id = ' . $currentRealModule['id'])
            ->where($taskDataListFilter);
        //
        $taskFields = [
            'task.id as task_id',
            'task.name as task_name',
            'task.code as task_code',
            'task.tenant_id as tenant_id',
            'task.executor as task_executor',
            'task.executor_tenant_id as executor_tenant_id',
            'task.code as task_code',
            'ppi.playlist_package_id',
            'entity.name',
            'entity.code',
            'entity.id',
        ];
        switch ($currentRealModule['code']) {
            case 'level':
            case 'asset':
                $taskDataListQuery
                    ->join("playlist_package_item ppi ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(entity.json,'$.{$currentRealModule['code']}_design'))");
                break;
            case 'design':
                $taskDataListQuery
                    ->join("playlist_package_item ppi ON ppi.entity_id = entity.id");
        }
        $taskDataList = $taskDataListQuery->field($taskFields)->select();
        $taskMaxVersionReviewList = [];
        $outsideTaskIdMap = [];
        if (count($taskDataList) > 0) {
            // 区分外包任务
            $outsideTaskList = [];
            $insideTaskList = [];
            foreach ($taskDataList as $taskData) {
                if ($taskData['executor_tenant_id'] != 0 && $taskData['executor_tenant_id'] != $taskData['tenant_id']) {
                    $outsideTaskList[$taskData['task_id']] = $taskData;
                } else {
                    $insideTaskList[$taskData['task_id']] = $taskData;
                }
            }
            $taskIdList = array_column($insideTaskList, 'task_id', 'task_id');
            if (count($outsideTaskList)) {
                // 通过订单查询外包任务真实数据
                $orderService = OrderService::getInstance();
                $outsideTaskIdMap = $orderService->getOutsideTaskListByTaskIdList(array_column($outsideTaskList, 'task_id'));
                $taskIdList += array_column($outsideTaskIdMap, 'id', 'id');
            }
            $taskMaxVersionIdList = $this->versionModel
                ->where([
                    'link_id' => ['IN', $taskIdList], 'module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
                    'is_deprecate' => 'no',
                ])
                ->field('max(id) as version_id')
                ->group('link_id')
                ->select();
            $taskMaxVersionIdList = array_column($taskMaxVersionIdList, 'version_id');
            $checkRoleCode = $this->getCheckRoleCode();
            $taskVersionReviewQueryFields = [
                'version.id',
                'version.link_id',
                'version.number',
                'version.is_publish',
                'version.is_pass',
                'review_request.id',
                'review_request.is_pass',
                'review_request.is_reviewed',
                'review_request.need_handle',
                'review_request_node.id',
                'review_request_node.is_active',
                'review_request_node.is_reviewed',
                'review_request_node.is_pass',
                'review_request_node.plan_reviewer',
                'review_request_node.role_code',
            ];
            if (count($taskMaxVersionIdList) > 0) {
                $taskMaxVersionReviewListFilter = [
                    'version.id' => ['IN', $taskMaxVersionIdList],
                    'version.module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
                ];
                $taskMaxVersionReviewList = $this->versionModel
                    ->join('review_request  ON review_request.link_id = version.id and review_request.module_id = ' . Module::$moduleDictData['module_index_by_code']['version']['id'])
                    ->join('review_request_node ON review_request.id = review_request_node.review_request_id AND review_request_node.role_code = \'' . $checkRoleCode . '\'', 'LEFT')
                    ->field(build_complex_query_fields($taskVersionReviewQueryFields, '__'))
                    ->where($taskMaxVersionReviewListFilter)
                    ->select();
                $taskMaxVersionReviewList = array_map(function ($item) {
                    return separate_complex_query_data($item, '__', 'version');
                }, $taskMaxVersionReviewList);
            }

            $taskDataList = array_group_by($taskDataList, 'playlist_package_id');
        }
        $versionSubmitMap = [];
        if (!empty($playlistVersionItemList)) {
            // versionSubmitMap
            $versionSubmitMap = array_column($playlistVersionItemList, 'version_id', 'version_id');
//            $playlistVersionItemList = array_group_by($playlistVersionItemList, 'playlist_version_id');
        }

        $playlistVersionList = array_column($playlistVersionList, null, 'playlist_package_id');
        $taskMaxVersionReviewList = array_column($taskMaxVersionReviewList, null, 'link_id');
        // 格式化结果
        // playlist-status -- '',submitted,done
        foreach ($playlistPackageList as &$playlistPackage) {
            $playlistPackage['playlist'] = $playlistList[$playlistPackage['id']] ?? null;
            $currentTaskList = $taskDataList[$playlistPackage['id']] ?? [];
            $currentLatestPlaylistVersion = $playlistVersionList[$playlistPackage['id']] ?? null;
//            $currentLatestPlaylistItemVersionList = [];
            $playlistPackage['status'] = '';
            if (!empty($currentLatestPlaylistVersion)) {
//                $currentLatestPlaylistItemVersionList = $playlistVersionItemList[$currentLatestPlaylistVersion['id']] ?? [];
//                $currentLatestPlaylistItemVersionList = array_column($currentLatestPlaylistItemVersionList, 'version_id');
                $playlistPackage['status'] = 'submitted';
            }
            $playlistPackage['submit_times'] = !empty($currentLatestPlaylistVersion) ? $currentLatestPlaylistVersion['number'] : 0;
            $playlistPackage['latest_playlist_version'] = $currentLatestPlaylistVersion;
            $passedVersionCount = 0;
            // task_status -- in_progress,wait_review,reviewing,modifying,wait_publish,done,
            foreach ($currentTaskList as &$taskData) {
                $realOutSideTaskInfo = $outsideTaskIdMap[$taskData['task_id']] ?? 0;
                if (!empty($realOutSideTaskInfo)) {
                    $latestVersion = $taskMaxVersionReviewList[$realOutSideTaskInfo['id']] ?? null;
                    $taskData['id'] = $realOutSideTaskInfo['entity_id'];
                    $taskData['task_id'] = $realOutSideTaskInfo['id'];
                    $taskData['tenant_id'] = $realOutSideTaskInfo['tenant_id'];
                } else {
                    $latestVersion = $taskMaxVersionReviewList[$taskData['task_id']] ?? null;
                }
                $taskData['latest_version'] = $latestVersion;
                $taskData['submit_times'] = !empty($latestVersion) ? $latestVersion['number'] : 0;
                if (!empty($latestVersion)) {
                    if ($latestVersion['is_pass'] === 'yes') {
                        if ($latestVersion['is_publish'] === 'yes') {
                            $taskData['status'] = 'done';
                            $passedVersionCount += 1;
                        } else {
                            $taskData['status'] = 'wait_publish';
                        }
                    } else {
                        //version is_pass = no
                        if ($latestVersion['review_request']['is_reviewed'] === 'yes') {
                            $taskData['status'] = 'modifying';
                        } else {
                            // review_request is_reviewed = no and version is_pass = no
                            // $latestVersion['review_request_node'] 为审核流程的组长节点
                            if ($latestVersion['review_request_node']['is_reviewed'] === 'no') {
                                // review_request is_reviewed = no and version is_pass = no and review_request_node is_reviewed = no
                                $taskData['status'] = 'in_progress';
                            } else {
                                // 检查是否提交过
                                if (in_array($latestVersion['id'], $versionSubmitMap)) {
                                    $taskData['status'] = 'reviewing';
                                } else {
                                    $taskData['status'] = 'wait_review';
                                }
                            }
                        }
                    }
                } else {
                    $taskData['status'] = 'in_progress';
                }
            }
            $currentTaskListCount = count($currentTaskList);
            $playlistPackage['count_data'] = [
                'done' => $passedVersionCount,
                'total' => $currentTaskListCount
            ];
            if ($passedVersionCount === $currentTaskListCount) {
                $playlistPackage['status'] = 'done';
            }
            $currentTaskList = array_filter($currentTaskList, function ($item) {
                return $item['status'] !== 'wait_publish';
            });
            $playlistPackage['children'] = array_values($currentTaskList);
            $res['rows'][] = $playlistPackage;
        }
        return $res;
    }

    /**
     * 已组装播放列表
     * @param $filter
     * @param $page
     * @param $order
     * @return array
     */
    public function assembledShotList($filter, $page, $order = 'playlist_package.id DESC')
    {
        $res = [
            'total' => 0,
            'rows' => [],
        ];
        $projectId = $filter['project_id'];
        $stepId = $filter['step_id'];
        $stepCategoryId = $filter['step_category_id'];
        $episodeCode = $filter['initial_episode_code'];
        $showingsNumberList = $filter['showings_number_list'] ?? [];
        $nameSearch = $filter['name'] ?? null;
        $planEndTime = $filter['plan_end_time'] ?? [];

        $playlistPackageFilter = [
            'playlist_package.project_id' => $projectId,
            'playlist_package.initial_episode_code' => $episodeCode,
//            'playlist_package.created_by' => $userId,
            'playlist_package.module_code' => 'shot',
//            'task.step_id' => $stepId,
        ];
        if (!empty($nameSearch)) {
            $playlistPackageFilter['playlist_package.name'] = $nameSearch;
        }
        if (!empty($planEndTime)) {
            $playlistPackageFilter['playlist_package.plan_end_time'] = $planEndTime;
        }
        if (!empty($showingsNumberList)) {
            $playlistPackageFilter['_string'] = '';
            $findInSetFilter = [];
            foreach ($showingsNumberList as $showingsNumber) {
                $findInSetFilter[] = 'FIND_IN_SET(\'' . $showingsNumber . '\', playlist_package.showings_number_str)';
            }
            $playlistPackageFilter['_string'] = implode('OR', $findInSetFilter);
        }

        // 判断当前要查询的实体是什么类型
        $stepCategory = $this->stepCategoryModel->find($stepCategoryId);
        if (empty($stepCategory)) {
            throw new LogicException('second level category not found', ErrorCode::STEP_CATEGORY_NOT_FOUND);
        }
        $topStepCategory = $this->stepCategoryModel->find($stepCategory['parent_id']);
        if (empty($topStepCategory)) {
            throw new LogicException('top category not found', ErrorCode::STEP_CATEGORY_NOT_FOUND);
        }
        $currentRealModule = Module::$moduleDictData['module_index_by_id'][$topStepCategory['entity_id']] ?? null;
        if (empty($currentRealModule)) {
            throw new LogicException('current module not found', ErrorCode::MODULE_DOES_NOT_EXIST);
        }

//        $playlistPackageCountQuery = $this->playlistPackageModel
//            ->join('playlist_package_item ppi ON ppi.playlist_package_id = playlist_package.id')
//            ->where($playlistPackageFilter)
//            ->order($order)->field('playlist_package.id')->group('playlist_package.id');
//
//        // 通过分类 关联不同的实体类
//        switch ($currentRealModule['code']) {
//            case 'shot':
//                $playlistPackageCountQuery
//                    ->join("entity ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(entity.json,'$.{$currentRealModule['code']}_storyboard'))");
//                break;
//            case 'sequence':
//                $shotModuleId = Module::$moduleDictData['module_index_by_code']['shot']['id'];
//                $sequenceModuleId = Module::$moduleDictData['module_index_by_code']['sequence']['id'];
//                // 查询序列任务的时候 只能通过镜头的中间关联 查询出真正的序列实体信息
//                $playlistPackageCountQuery
//                    ->join("INNER JOIN (select * from entity where module_id = $shotModuleId and project_id = $projectId and initial_episode_code = '$episodeCode') as shot ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(shot.json,'$.shot_storyboard'))")
//                    ->join("INNER JOIN (select * from entity where module_id = $sequenceModuleId and project_id = $projectId and initial_episode_code = '$episodeCode') as entity ON entity.id = shot.entity_id");
//                break;
//            case 'storyboard':
//                $playlistPackageCountQuery
//                    ->join("playlist_package_item ppi ON ppi.entity_id = entity.id");
//        }
//
//        $res['total'] = $this->playlistPackageModel->query("select count(*) as count from " . $playlistPackageCountQuery->join('task on task.entity_id = entity.id')->buildSql() . ' sub_count_query');
//
//        $res['total'] = intval($res['total'][0]['count']);
        $res['total'] = $this->playlistPackageModel->where($playlistPackageFilter)->count();
        if ($res['total'] === 0) {
            return $res;
        }

//        $playlistPackageQuery = $this->playlistPackageModel
//            ->join('playlist_package_item ppi ON ppi.playlist_package_id = playlist_package.id')
//            ->where($playlistPackageFilter)
//            ->order($order)->field('playlist_package.id')->group('playlist_package.id')
//            ->page(...$page);
//
//        // 通过分类 关联不同的实体类
//        switch ($currentRealModule['code']) {
//            case 'shot':
//                $playlistPackageQuery
//                    ->join("entity ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(entity.json,'$.{$currentRealModule['code']}_storyboard'))");
//                break;
//            case 'sequence':
//                $shotModuleId = Module::$moduleDictData['module_index_by_code']['shot']['id'];
//                $sequenceModuleId = Module::$moduleDictData['module_index_by_code']['sequence']['id'];
//                // 查询序列任务的时候 只能通过镜头的中间关联 查询出真正的序列实体信息
//                $playlistPackageQuery
//                    ->join("INNER JOIN (select * from entity where module_id = $shotModuleId and project_id = $projectId and initial_episode_code = '$episodeCode') as shot ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(shot.json,'$.shot_storyboard'))")
//                    ->join("INNER JOIN (select * from entity where module_id = $sequenceModuleId and project_id = $projectId and initial_episode_code = '$episodeCode') as entity ON entity.id = shot.entity_id");
//                break;
//            case 'storyboard':
//                $playlistPackageQuery
//                    ->join("playlist_package_item ppi ON ppi.entity_id = entity.id");
//        }
//
//        $playlistPackageIdList = $playlistPackageQuery->join('task on task.entity_id = entity.id')->select();
//        if (count($playlistPackageIdList) === 0) {
//            return $res;
//        }

        // 查询审核包
        $playlistPackageList = $this->playlistPackageModel
            ->where($playlistPackageFilter)
            ->page(...$page)
            ->order($order)
            ->select();

        if (count($playlistPackageList) === 0) {
            return $res;
        }

        $playlistPackageIdList = array_column($playlistPackageList, 'id');
        $playlistVersionFilter = [
            'playlist_package_id' => ['IN', $playlistPackageIdList],
            'initial_episode_code' => $episodeCode,
            'step_category_id' => $stepCategoryId,
            'step_id' => $stepId,
        ];

        $maxPlaylistVersionList = $this->playlistVersionModel
            ->where($playlistVersionFilter)
            ->field('max(id) id')
            ->group('playlist_package_id')
            ->select();
        $maxPlaylistVersionIdList = array_column($maxPlaylistVersionList, 'id');
        $playlistVersionList = [];
        $playlistVersionItemList = [];
        if (count($maxPlaylistVersionIdList) > 0) {
            $playlistVersionList = $this->playlistVersionModel->where(['id' => ['IN', $maxPlaylistVersionIdList]])->select();
            $playlistVersionItemList = $this->playlistItemVersionModel
                ->where(['playlist_version_id' => ['IN', $maxPlaylistVersionIdList]])
                ->select();
        }


        $taskDataListFilter = [
            "ppi.playlist_package_id" => ['IN', $playlistPackageIdList],
            'task.step_type' => 'step',
            'task.step_category_id' => $stepCategoryId,
            'task.step_id' => $stepId,
        ];
        $taskDataListQuery = $this->taskModel
            ->join('entity on entity.id = task.entity_id and module_id = ' . $currentRealModule['id'])
            ->where($taskDataListFilter);
        //
        $taskFields = [
            'task.id as task_id',
            'task.name as task_name',
            'task.code as task_code',
            'task.code as task_code',
            'task.tenant_id as tenant_id',
            'task.executor as task_executor',
            'task.executor_tenant_id as executor_tenant_id',
            'ppi.playlist_package_id',
            'entity.name',
            'entity.code',
            'entity.id',
            'entity.entity_id',
            'entity.entity_module_id',
        ];
        // 通过分类 关联不同的实体类
        switch ($currentRealModule['code']) {
            case 'shot':
                $taskDataListQuery
                    ->join("playlist_package_item ppi ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(entity.json,'$.{$currentRealModule['code']}_storyboard'))");
                break;
            case 'sequence':
                $shotModuleId = Module::$moduleDictData['module_index_by_code']['shot']['id'];
                // 查询序列任务的时候 只能通过镜头的中间关联 查询出真正的序列实体信息
                $taskDataListQuery
                    ->join("INNER JOIN (select * from entity where module_id = $shotModuleId and project_id = $projectId and initial_episode_code = '$episodeCode') as shot ON entity.id = shot.entity_id")
                    ->join("playlist_package_item ppi ON ppi.entity_id = JSON_UNQUOTE(JSON_EXTRACT(shot.json,'$.shot_storyboard'))")
                    ->group('entity.id');
                break;
            case 'storyboard':
                $taskDataListQuery
                    ->join("playlist_package_item ppi ON ppi.entity_id = entity.id");
        }
        $taskDataList = $taskDataListQuery->field($taskFields)->select();
        $taskMaxVersionReviewList = [];
        if (count($taskDataList) > 0) {

            // 如果当前是镜头 那么需要额外查询序列信息
            $parentEntityList = [];
            if ($currentRealModule['code'] === 'shot') {
                $parentEntityIdList = array_column($taskDataList, 'entity_id');
                $queryParentEntityId = [];
                foreach ($parentEntityIdList as $entityId) {
                    if ($entityId > 0 && !in_array($entityId, $queryParentEntityId)) {
                        $queryParentEntityId[] = $entityId;
                    }
                }
                if (count($queryParentEntityId)) {
                    $parentEntityList = $this->entityModel->where(['id' => ['IN', $queryParentEntityId]])->field('id,name,code')->select();
                    $parentEntityList = array_column($parentEntityList, null, 'id');
                }
                foreach ($taskDataList as &$taskDataItem) {
                    $sequence = $parentEntityList[$taskDataItem['entity_id']] ?? ['name' => '未知sequence'];
                    $taskDataItem['name'] = $sequence['name'];
                }
            }
            // 区分外包任务
            $outsideTaskList = [];
            $insideTaskList = [];
            foreach ($taskDataList as $taskData) {
                if ($taskData['executor_tenant_id'] != 0 && $taskData['executor_tenant_id'] != $taskData['tenant_id']) {
                    $outsideTaskList[$taskData['task_id']] = $taskData;
                } else {
                    $insideTaskList[$taskData['task_id']] = $taskData;
                }
            }
            $taskIdList = array_column($insideTaskList, 'task_id', 'task_id');
            if (count($outsideTaskList)) {
                // 通过订单查询外包任务真实数据
                $orderService = OrderService::getInstance();
                $outsideTaskIdMap = $orderService->getOutsideTaskListByTaskIdList(array_column($outsideTaskList, 'task_id'));
                $taskIdList += array_column($outsideTaskIdMap, 'id', 'id');
            }

            // @update 2021年8月3日 不查询已经弃用的版本数据
            $taskMaxVersionIdList = $this->versionModel
                ->where([
                    'link_id' => ['IN', $taskIdList], 'module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
                    'is_deprecate' => 'no',
                ])
                ->field('max(id) as version_id')
                ->group('link_id')
                ->select();
            $taskMaxVersionIdList = array_column($taskMaxVersionIdList, 'version_id');
            $checkRoleCode = $this->getCheckRoleCode();
            $taskVersionReviewQueryFields = [
                'version.id',
                'version.link_id',
                'version.number',
                'version.is_publish',
                'version.is_pass',
                'review_request.is_pass',
                'review_request.is_reviewed',
                'review_request.need_handle',
                'review_request_node.is_active',
                'review_request_node.is_reviewed',
                'review_request_node.is_pass',
                'review_request_node.plan_reviewer',
                'review_request_node.role_code',
            ];
            if (count($taskMaxVersionIdList) > 0) {
                $taskMaxVersionReviewListFilter = [
                    'version.id' => ['IN', $taskMaxVersionIdList],
                    'version.module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
                ];
                $taskMaxVersionReviewList = $this->versionModel
                    ->join('review_request  ON review_request.link_id = version.id and review_request.module_id = ' . Module::$moduleDictData['module_index_by_code']['version']['id'])
                    ->join('review_request_node ON review_request.id = review_request_node.review_request_id AND review_request_node.role_code = \'' . $checkRoleCode . '\'', 'LEFT')
                    ->field(build_complex_query_fields($taskVersionReviewQueryFields, '__'))
                    ->where($taskMaxVersionReviewListFilter)
                    ->select();
                $taskMaxVersionReviewList = array_map(function ($item) {
                    return separate_complex_query_data($item, '__', 'version');
                }, $taskMaxVersionReviewList);
            }

            $taskDataList = array_group_by($taskDataList, 'playlist_package_id');
        }

        if (!empty($playlistVersionItemList)) {
            $playlistVersionItemList = array_group_by($playlistVersionItemList, 'playlist_version_id');
        }

        $playlistVersionList = array_column($playlistVersionList, null, 'playlist_package_id');
        $taskMaxVersionReviewList = array_column($taskMaxVersionReviewList, null, 'link_id');
        foreach ($playlistPackageList as &$playlistPackage) {
            $currentTaskList = $taskDataList[$playlistPackage['id']] ?? [];
            $currentLatestPlaylistVersion = $playlistVersionList[$playlistPackage['id']] ?? null;
            $currentLatestPlaylistItemVersionList = [];
            $playlistPackage['status'] = '';
            if (!empty($currentLatestPlaylistVersion)) {
                $currentLatestPlaylistItemVersionList = $playlistVersionItemList[$currentLatestPlaylistVersion['id']] ?? [];
                $currentLatestPlaylistItemVersionList = array_column($currentLatestPlaylistItemVersionList, 'version_id');
                $playlistPackage['status'] = 'submitted';
            }
            $playlistPackage['submit_times'] = !empty($currentLatestPlaylistVersion) ? $currentLatestPlaylistVersion['number'] : 0;
            $playlistPackage['latest_playlist_version'] = $currentLatestPlaylistVersion;
            $passedVersionCount = 0;
            foreach ($currentTaskList as &$taskData) {
                $realOutSideTaskInfo = $outsideTaskIdMap[$taskData['task_id']] ?? 0;
                if (!empty($realOutSideTaskInfo)) {
                    $latestVersion = $taskMaxVersionReviewList[$realOutSideTaskInfo['id']] ?? null;
                    $taskData['id'] = $realOutSideTaskInfo['entity_id'];
                    $taskData['task_id'] = $realOutSideTaskInfo['id'];
                    $taskData['tenant_id'] = $realOutSideTaskInfo['tenant_id'];
                } else {
                    $latestVersion = $taskMaxVersionReviewList[$taskData['task_id']] ?? null;
                }
                $taskData['latest_version'] = $latestVersion;
                $taskData[Module::$moduleDictData['module_index_by_id'][$taskData['entity_module_id']]['code']] = $parentEntityList[$taskData['entity_id']] ?? null;
                $taskData['submit_times'] = !empty($latestVersion) ? $latestVersion['number'] : 0;
                if (!empty($latestVersion)) {
                    if ($latestVersion['is_pass'] === 'yes') {
                        if ($latestVersion['is_publish'] === 'yes') {
                            $taskData['status'] = 'done';
                            $passedVersionCount += 1;
                        } else {
                            $taskData['status'] = 'wait_publish';
                        }
                    } else {
                        //version is_pass = no
                        if ($latestVersion['review_request']['is_reviewed'] === 'yes') {
                            $taskData['status'] = 'modifying';
                        } else {
                            // review_request is_reviewed = no and version is_pass = no
                            // $latestVersion['review_request_node'] 为审核流程的组长节点
                            if ($latestVersion['review_request_node']['is_reviewed'] === 'no') {
                                // review_request is_reviewed = no and version is_pass = no and review_request_node is_reviewed = no
                                $taskData['status'] = 'in_progress';
                            } else {
                                // 检查是否提交过
                                if (in_array($latestVersion['id'], $currentLatestPlaylistItemVersionList)) {
                                    $taskData['status'] = 'reviewing';
                                } else {
                                    $taskData['status'] = 'wait_review';
                                }
                            }
                        }
                    }
                } else {
                    $taskData['status'] = 'in_progress';
                }
            }
            $currentTaskListCount = count($currentTaskList);
            $playlistPackage['count_data'] = [
                'done' => $passedVersionCount,
                'total' => $currentTaskListCount
            ];
            if ($passedVersionCount === $currentTaskListCount) {
                $playlistPackage['status'] = 'done';
            }
//            $currentTaskList = array_filter($currentTaskList, function ($item) {
//                return $item['status'] !== 'wait_publish';
//            });
            $playlistPackage['children'] = $currentTaskList;
            $res['rows'][] = $playlistPackage;
        }
        return $res;
    }

    /**
     * 等待组装镜头任务列表
     * @param int $tenantId
     * @param $filter
     * @param $page
     * @return array
     * @throws Exception
     */
    public function waitAssembleStoryboardList(int $tenantId, $filter, $page)
    {
        $filter['tenant_id'] = $tenantId;
        $filter['module_id'] = Module::$moduleDictData['module_index_by_code']['storyboard']['id'];
        $publishedStatus = StatusService::getInstance()->getOne(['code' => 'task_generated'], 'id,name,code');
        $filter['storyboard_status'] = $publishedStatus['id'];
        $param = [
            'filter' => $filter,
            'fields' => 'storyboard.id,storyboard.name,storyboard.code,storyboard.initial_episode_code,storyboard.showings_number,storyboard.entity_id,storyboard.storyboard_sequence',
            'page' => $page,
        ];
        $res = EntityService::getInstance()->getStoryboardSequenceList($param, $tenantId, 'storyboard');
        foreach ($res['rows'] as &$row) {
            $row['entity_id_list'] = array_column(array_column($row['storyboard_list'], 'storyboard'), 'id');
        }
        return $res;
    }

    /**
     * 获得下一个审核角色code
     * @param $task
     * @param $currentRoleCode
     * @return array
     */
    public function getNextReviewRoleCode($task, $currentRoleCode)
    {

        $nextReviewRoleCode = "";
        if (empty($task)) {
            throw new LogicException('task relation config missing ', ErrorCode::REVIEW_WORKFLOW_CONFIG_NOT_FOUND);
        }
        $reviewWorkflowService = ReviewWorkflowService::getInstance();
        $projectReviewWorkflowRelation = $reviewWorkflowService->getTaskReviewWorkflowRelationConfig($task['id'], $task['project_id'], $task['step_workflow_id'], $task['step_id']);
        if (empty($projectReviewWorkflowRelation)) {
            throw new LogicException('project review workflow relation config missing ', ErrorCode::REVIEW_WORKFLOW_CONFIG_NOT_FOUND);
        }
        $reviewWorkflow = model(ReviewWorkflowModel::class)->where(['id' => $projectReviewWorkflowRelation['review_workflow_id']])->getField('config');
        $reviewWorkflow = json_decode($reviewWorkflow, true);
        $roleCode = array_column($reviewWorkflow['nodes']['reviewer'], 'role');
        $roleCodeIndex = array_search($currentRoleCode, $roleCode);
        $roleCodeIndex = $roleCodeIndex + 1;

        if ($roleCodeIndex !== count($roleCode)) { //判断是不是最后一个,如果不是获取下一个节点
            $nextReviewRoleCode = $roleCode[$roleCodeIndex];
        }


        return $nextReviewRoleCode;
    }

    /**
     * 提交审核
     * @param int $getUserId
     * @param $tenantId
     * @param $data
     * @return array
     * @throws \Exception
     */
    public function submitReview(int $getUserId, $tenantId, $data)
    {
        $taskVersionReviewData = $data['task_version_review_data'];
        $planEndTime = $data['plan_end_time'];
        $moduleCode = $data['module_code'];
        $stepCategoryId = $data['step_category_id'];
        $name = $data['name'];
        $projectId = $data['project_id'];
        $taskIdList = array_column($taskVersionReviewData, 'task_id');

        //有外包任务的转换成外包任务id
        $taskMap = $this->conversionInsideIdMap($taskIdList);
        $taskIds = $taskMap['task_ids'];
        $outsideTaskIdMap = $taskMap['b_to_a_map'];
        $insideTaskIdMap = $taskMap['a_to_b_map'];

        // 查询出提交审核的版本信息
        // 最大版本 已通过组长审核
        // 外包任务 需要判断review_request的租户id为当前租户id 因为外包任务需要审核两次
        $maxVersionFilter = [
            'version.module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
            'version.link_id' => ['IN', implode(',', $taskIds)],
            'version.is_deprecate' => 'no',
            'review_request.need_handle' => 'yes',
            'review_request.tenant_id' => $tenantId,
            [
                'review_request.is_reviewed' => 'no',
                'review_request.is_pass' => 'yes',
                '_logic' => 'or',
            ],
        ];

        $maxVersionIdList = $this->versionModel
            ->join('review_request on review_request.link_id = version.id and review_request.module_id = ' . Module::$moduleDictData['module_index_by_code']['version']['id'])
            ->where($maxVersionFilter)
            ->field('max(version.id) as id')->group('version.link_id')->select();

        if (empty($maxVersionIdList)) {
            throw new LogicException('version not exist', ErrorCode::DATA_INVALID);
        }


        $maxVersionIdList = array_column($maxVersionIdList, 'id');
        $versionReviewRequestList = $this->versionModel
            ->join('review_request on version.id = review_request.link_id and review_request.module_id = ' . Module::$moduleDictData['module_index_by_code']['version']['id'])
            ->where(['version.id' => ['IN', $maxVersionIdList], 'review_request.tenant_id' => $tenantId])
            ->field('version.id as version_id,version.link_id as task_id,review_request.id as review_request_id,review_request.is_reviewed,version.project_id')
            ->select();

        $needReviewCount = array_filter($versionReviewRequestList, function ($item) {
            return $item['is_reviewed'] === 'no';
        });
        if (count($needReviewCount) === 0) {
            throw new LogicException('don`t need submit review', ErrorCode::DATA_INVALID);
        }
        $versionLinkId = [];  //任务id
        $versionListMap = []; //任务映射
        $taskReviewRequestMap = []; //审核任务映射
        foreach ($versionReviewRequestList as $versionReviewRequestListItem) {
            if (!in_array($versionReviewRequestListItem['task_id'], $versionLinkId)) {
                $versionLinkId[] = $versionReviewRequestListItem['task_id'];
            }
            if (!array_key_exists($versionReviewRequestListItem['task_id'], $versionListMap)) {
                $versionListMap[$versionReviewRequestListItem['task_id']] = $versionReviewRequestListItem;
            }
            if (!array_key_exists($versionReviewRequestListItem['review_request_id'], $taskReviewRequestMap)) {
                $taskReviewRequestMap[$versionReviewRequestListItem['review_request_id']] = $versionReviewRequestListItem['task_id'];
            }
        }
        //查询出甲方任务的状态
        $partyATaskMap = [];
        $partyATaskEntityIds = [];
        if (!empty($outsideTaskIdMap)) {
            $partyATask = model(TaskModel::class)->where(['id' => ['IN', array_values($outsideTaskIdMap)]])->field('id,entity_id,deal_status')->select();
            $partyATaskMap = array_column($partyATask, null, 'id');
            $partyATaskEntityIds = array_unique(array_column($partyATask, 'entity_id'));
        }

        $versionTask = model(TaskModel::class)->where(['id' => ['IN', $versionLinkId]])->field('entity_id,id,deal_status,step_id')->select();

        $versionTaskEntityIdMap = [];
        $stepId = 0;
        foreach ($versionTask as $versionTaskItem) {
            $versionTaskEntityIdMap[$versionTaskItem['id']] = $versionTaskItem;
            if (empty($stepId)) {
                $stepId = $versionTaskItem['step_id'];
            } elseif ($stepId != $versionTaskItem['step_id']) {
                throw new LogicException('tasks step is not the same', ErrorCode::TASKS_STEP_IS_NOT_THE_SAME);
            }
        }

        //比对出不可提交的任务
        $noSubmittedTaskId = array_diff($taskIdList, $versionLinkId);
        $noSubmittedTaskEntityIdMap = [];
        $noSubmittedTaskEntityIds = [];
        if (!empty($noSubmittedTaskId)) {
            $noSubmittedVersionTask = model(TaskModel::class)->where(['id' => ['IN', $noSubmittedTaskId]])->field('entity_id,id,deal_status')->select();
            $noSubmittedTaskEntityIdMap = array_column($noSubmittedVersionTask, null, 'id');
            $noSubmittedTaskEntityIds = array_unique(array_column($noSubmittedVersionTask, 'entity_id'));
        }

        //检验审核流节点
        $reviewRequestIds = array_column($versionReviewRequestList, 'review_request_id');
        $reviewRequestNode = $this->reviewRequestNodeModel->where(['review_request_id' => ["IN", $reviewRequestIds]])->field('id,role_code,parent_id,review_request_id')->select();
        $checkRoleCode = $this->getCheckRoleCode();
        $reviewRequestNodeGroup = array_group_by($reviewRequestNode, 'review_request_id');
        $isAllSyncRoleCodes = null;
        $currentReviewCode = "";
        $reviewRequestNodeIds = [];
        $toSubmitTask = [];

        foreach ($reviewRequestNodeGroup as $groupReviewRequestId => $groupReviewRequestItem) {
            $groupReviewRequestItem = array_sort_by($groupReviewRequestItem, 'parent_id');

            $matchCheckRole = false;
            $afterCheckRoleNode = null;
            $roleCodes = '';
            foreach ($groupReviewRequestItem as $reviewRequestNode) {
                $roleCodes .= $reviewRequestNode['role_code'];
                if ($matchCheckRole === false && $reviewRequestNode['role_code'] === $checkRoleCode) {
                    $matchCheckRole = true;
                    continue;
                }
                if ($matchCheckRole && empty($afterCheckRoleNode)) {
                    $afterCheckRoleNode = $reviewRequestNode;
                }
            }

            if ($afterCheckRoleNode === null) {
                throw new LogicException('task do not need ' . $checkRoleCode . ' after role review', ErrorCode::DATA_INVALID);
            }
            //当前审核版本的审核角色
            $currentReviewCode = $afterCheckRoleNode['role_code'];

            //判断任务之间的审核节点是否相同
            if (empty($isAllSyncRoleCodes)) {
                $isAllSyncRoleCodes = $roleCodes;
            } elseif ($isAllSyncRoleCodes != $roleCodes) {
                throw new LogicException(' tasks between review request node are not the same', ErrorCode::TASKS_BETWEEN_REVIEW_REQUEST_NODE_ARE_NOT_THE_SAME);
            }
            //如果为待提交的需要修改审核节点的激活状态
            //先判断外包任务的
            if (array_key_exists($taskReviewRequestMap[$groupReviewRequestId], $outsideTaskIdMap)) {
                //判断甲方是否存在该任务
                if (!array_key_exists($outsideTaskIdMap[$taskReviewRequestMap[$groupReviewRequestId]], $partyATaskMap)) {
                    throw new LogicException('party a task not exist', ErrorCode::TASK_NOT_EXIST);
                } elseif ($partyATaskMap[$outsideTaskIdMap[$taskReviewRequestMap[$groupReviewRequestId]]]['deal_status'] === 'to_submit') {
                    $toSubmitTask[] = $outsideTaskIdMap[$taskReviewRequestMap[$groupReviewRequestId]];
                    $reviewRequestNodeIds[] = $afterCheckRoleNode['id'];
                }
            } elseif ($versionTaskEntityIdMap[$taskReviewRequestMap[$groupReviewRequestId]]['deal_status'] === 'to_submit') {
                $toSubmitTask[] = $taskReviewRequestMap[$groupReviewRequestId];
                $reviewRequestNodeIds[] = $afterCheckRoleNode['id'];
            }
        }

        //获取相关的实体分类,用于审核流映射
        $versionTaskEntityIds = array_unique(array_column($versionTask, 'entity_id'));

        $entityIds = array_merge($versionTaskEntityIds, $partyATaskEntityIds, $noSubmittedTaskEntityIds);

        $entityList = model(EntityModel::class)
            ->join('module on module.id = entity.module_id')
            ->where(['entity.id' => ['IN', $entityIds]])
            ->field('entity.id,entity.module_id,entity.initial_episode_code,entity.showings_number,entity.json,module.name as module_name')->select();


        $assetModuleIds = [
            module_by_code('asset')['id'], module_by_code('level')['id'], module_by_code('design')['id'],
        ];
        $param = "";
        $currentAttributes = "";
        $playlistVersionInitialEpisodeCode = [];
        $entityEpisodeCodeMap = [];
        foreach ($entityList as $entityListItem) {
            if (in_array($entityListItem["id"], $versionTaskEntityIds)) {
                $itemParam = json_decode($entityListItem['json'], true);
                if (empty($param)) {
                    $param = $itemParam;
                }
                //只有资产的才判断等级和类型是否相同
                if (in_array($entityListItem['module_id'], $assetModuleIds)) {
                    $moduleCategory = "{$entityListItem['module_name']}_category";
                    $moduleGrade = $itemParam["{$entityListItem['module_name']}_grade"] ?? "";
                    $moduleCategoryGrade = "{$moduleCategory}_{$moduleGrade}";
                    if (empty($currentAttributes)) {
                        $currentAttributes = $moduleCategoryGrade;
                    } elseif ($currentAttributes != $moduleCategoryGrade) {
                        throw new LogicException('entity category or grade is not the same', ErrorCode::ENTITY_CATEGORY_OR_GRADE_IS_NOT_THE_SAME);
                    }
                }
                if (!empty($entityListItem['initial_episode_code']) && !in_array($entityListItem['initial_episode_code'], $playlistVersionInitialEpisodeCode)) {
                    $playlistVersionInitialEpisodeCode[] = $entityListItem['initial_episode_code'];
                }
            }

            $entityEpisodeCodeMap[$entityListItem['id']] = $entityListItem['initial_episode_code'];
        }
        $playlistVersionInitialEpisodeCode = join(",", $playlistVersionInitialEpisodeCode);


        $playlistVersionData = [
            'name' => $name,
            'number' => 1,
            'initial_episode_code' => $playlistVersionInitialEpisodeCode,
            'module_code' => $moduleCode,
            'showings_number_str' => "",
            'current_review_code' => $currentReviewCode,
            'playlist_id' => 0,
            'playlist_package_id' => 0,
            'step_category_id' => $stepCategoryId,
            'step_id' => $stepId,
            'plan_end_time' => strtotime($planEndTime),
            'created_by' => $getUserId,
            'status' => 'reviewing',
            'tenant_id' => $tenantId,
            'project_id' => $projectId,
            'param' => $param,
            'current_schedule_code' => $currentReviewCode,
        ];
        $res = [];
        $playlistVersion = model(PlaylistVersionModel::class)->addItem($playlistVersionData);
        $res['playlist_version'] = $playlistVersion;
        $versionSecondSubmitData = [];
        //创建审核版本子项
        if ($playlistVersion) {
            $playlistItemVersionData = [];
            //需要按任务来补充，如果没有查询到所需版本的审核，证明为不可提交的，审核与版本直接填0
            foreach ($taskIdList as $taskIdItem) {
                $tmp = [
                    'current_review_code' => $currentReviewCode,
                    'initial_episode_code' => '',
                    'playlist_version_id' => $playlistVersion['id'],
                    'task_id' => $taskIdItem,
                    'entity_id' => 0,
                    'review_request_id' => 0,
                    'version_id' => 0,
                    'status' => 'reviewing',
                    'tenant_id' => $tenantId,
                    'created' => time(),
                    'created_by' => $getUserId,
                    'playlist_id' => 0,
                    "playlist_item_id" => 0,
                ];
                //TODO deal_status的状态默认为 no_submit ,如果存在下方的任务则修改为submitted

                //判断该任务是否存在乙方任务 ,如果存在
                if (array_key_exists($taskIdItem, $partyATaskMap)) {
                    $tmp['entity_id'] = $partyATaskMap[$taskIdItem]['entity_id'];
                    if (array_key_exists($taskIdItem, $insideTaskIdMap) && array_key_exists($insideTaskIdMap[$taskIdItem], $versionListMap)) { //通过甲方找乙方对应的review_request
                        $tmp['review_request_id'] = $versionListMap[$insideTaskIdMap[$taskIdItem]]['review_request_id'];
                        $tmp['version_id'] = $versionListMap[$insideTaskIdMap[$taskIdItem]]['version_id'];
                    }
                    $tmp['deal_status'] = 'submitted';
                } elseif (in_array($taskIdItem, $versionLinkId)) {
                    $tmp['entity_id'] = $versionTaskEntityIdMap[$taskIdItem]['entity_id'];
                    $tmp['review_request_id'] = $versionListMap[$taskIdItem]['review_request_id'];
                    $tmp['version_id'] = $versionListMap[$taskIdItem]['version_id'];
                    $tmp['deal_status'] = 'submitted';
                } elseif (array_key_exists($taskIdItem, $noSubmittedTaskEntityIdMap)) {
                    $tmp['entity_id'] = $noSubmittedTaskEntityIdMap[$taskIdItem]['entity_id'];
                    $tmp['deal_status'] = $noSubmittedTaskEntityIdMap[$taskIdItem]['deal_status'];
                }

                $tmp['initial_episode_code'] = $entityEpisodeCodeMap[$tmp['entity_id']] ?? '';
                if ($tmp['version_id'] > 0) {
                    $versionSecondSubmitData[] = $tmp['version_id'];
                }
                $playlistItemVersionData[] = $tmp;
            }
            $addAllPlaylistItemVersion = $this->playlistItemVersionModel->addAll($playlistItemVersionData);
            $res['playlist_item_version'] = $addAllPlaylistItemVersion;
            if ($addAllPlaylistItemVersion) {
                //如果为待提交的需要修改审核节点的激活状态
                if (!empty($reviewRequestNodeIds)) {
                    model(ReviewRequestNodeModel::class)->where(["id" => ["IN", $reviewRequestNodeIds]])->save(['is_active' => 'yes']);
                }

                //更新任务状态为以提交
                if (!empty($toSubmitTask)) {
                    model(TaskModel::class)->where(["id" => ["IN", $toSubmitTask]])->save(['deal_status' => 'submitted']);
                }

                if (!empty($versionSecondSubmitData)) {
                    $this->versionModel->where(['id' => ['IN', $versionSecondSubmitData]])->save(['is_second_submit' => 'yes']);
                }
            }

            // 制片提交审核任务，减少未处理数据记录
            Client::send('count_pending', build_queue_data_with_xu([
                'type' => 'review_submit',
                'mode' => 'sub_batch',
                'data' => $versionLinkId
            ]));

        }
        return $res;
    }

    /**
     * 转内部任务id为外部任务id
     * @param $taskIdList
     * @return array|array[]
     */
    public function conversionInsideIdMap($taskIdList)
    {
        //传入甲方id
        if (empty($taskIdList)) {
            return [
                "b_to_a_map" => [],
                "a_to_b_map" => [],
                "task_ids" => [],
            ];
        }

        $taskList = model(TaskModel::class)->where(['id' => ['IN', $taskIdList]])->field('id,executor_tenant_id,tenant_id,executor')->select();
        //将外包任务中的任务id替换
        $insideTaskList = [];
        $outsideTaskList = [];
        foreach ($taskList as &$taskData) {
            if ($taskData['executor_tenant_id'] != 0 && $taskData['executor_tenant_id'] != $taskData['tenant_id']) {
                $outsideTaskList[$taskData['id']] = $taskData;
                $outsideSupplierTenantId['executor_tenant_id'] = $taskData['executor_tenant_id'];
            } else {
                $insideTaskList[$taskData['id']] = $taskData;
                $executorUserIdList['executor'] = $taskData['executor'];

            }
        }

        $insideTaskList = array_column($insideTaskList, 'id', 'id');
        $outsideTaskList = array_column($outsideTaskList, 'id');
        return $this->getOutsideMap($insideTaskList, $outsideTaskList);
    }

    /**
     * 获取甲方与乙方的映射
     * @param $insideTaskList
     * @param $outsideTaskList
     * @return array
     */
    public function getOutsideMap($insideTaskList, $outsideTaskList)
    {
        $outsideTaskMap = [];
        if (!empty($outsideTaskList)) {
            // 通过订单查询外包任务真实数据
            $orderService = OrderService::getInstance();
            $outsideTaskMap = $orderService->getOutsideTaskListByTaskIdList($outsideTaskList);
            $insideTaskList += array_column($outsideTaskMap, 'id', 'id');
        }

        //通过乙方找甲方
        $outsideTaskIdMap = [];
        $insideTaskIdMap = [];
        foreach ($outsideTaskMap as $taskId => $outsideTaskMapItem) {
            if (!empty($outsideTaskMapItem)) {
                $outsideTaskIdMap[$outsideTaskMapItem['id']] = $taskId;
                $insideTaskIdMap[$taskId] = $outsideTaskMapItem['id'];
            }
        }
        return [
            "b_to_a_map" => $outsideTaskIdMap,  //乙方对甲方的映射
            "a_to_b_map" => $insideTaskIdMap,  //甲方对乙方的映射
            "task_ids" => $insideTaskList, //甲方id与甲方对应的乙方任务id融合
        ];
    }

    /**
     * 获得用户角色codeList
     * @param int $getUserId
     * @return array
     */
    public function getRoleCodeList(int $getUserId)
    {
        $userInfo = LoginService::getInstance()->getUserInfo($getUserId, false);
        $roleCode = [];
        foreach ($userInfo['role_info'] as $roleInfo) {
            $roleCode[] = $roleInfo['code'];
        }
        return array_unique($roleCode);
    }

    /**
     * 待审核播放列表
     * @param int $getUserId
     * @param $filter
     * @param $moduleCode
     * @param array $page
     * @param string $order
     * @return array|false|mixed|string
     * @throws \Exception
     */
    public function waitReviewPlayListVersion(int $getUserId, $filter, $moduleCode, array $page, $order = 'id DESC')
    {
//        $roleCode = $this->getRoleCodeList($getUserId);
//        $filterRoleCode = $filter['playlist_version.current_review_code'] ?? '';
//        if (empty($filterRoleCode)) {
//            throw new Exception("missing param.filter.playlist_version.current_review_code", ErrorCode::REQUEST_PARAM_ERROR);
//        }

//        $filter['rrn.role_code'] = $filterRoleCode;
        $filter['rrn.is_reviewed'] = 'no';
        $filter['rrn.is_active'] = 'yes';

        $moduleCodeStepCategory = OptionsService::getInstance()->getOptionsConfigItemData('assign_task_list_step_category_filter_config', $moduleCode, 'shot');

        if (empty($moduleCodeStepCategory)) {
            return [];
        }

        if (!isset($filter['playlist_version.step_category_id'])) {
            $filter['playlist_version.step_category_id'] = ['IN', $moduleCodeStepCategory];
        }


        $playlistVersionIdList = $this->playlistVersionModel
            ->join('playlist_item_version piv on playlist_version.id = piv.playlist_version_id')
            ->join('review_request_node rrn on rrn.review_request_id = piv.review_request_id and rrn.plan_reviewer = ' . $getUserId)
            ->where($filter)
            ->order($order)
            ->page(...$page)
            ->field('playlist_version.id')
            ->group('playlist_version.id')
            ->select();

        if (empty($playlistVersionIdList)) {
            return [];
        }
        $filter = [
            'id' => ['IN', array_column($playlistVersionIdList, 'id')]
        ];
        $playlistVersionList = $this->playlistVersionModel
            ->where($filter)
            ->order($order)
            ->select();

        $playlistVersionIdList = [];
        $playlistVersionStepIdList = [];
        $playlistVersionCurrentRoleFilter = [];
        foreach ($playlistVersionList as $playlistVersionListItem) {
            $playlistVersionIdList[] = $playlistVersionListItem['id'];
            $playlistVersionStepIdList[] = $playlistVersionListItem['step_id'];
            $playlistVersionCurrentRoleFilter[] = [
                "playlist_item_version.playlist_version_id" => $playlistVersionListItem['id'],
                "playlist_item_version.current_review_code" => $playlistVersionListItem['current_review_code']
            ];
        }

        $playlistVersionCurrentRoleFilter["_logic"] = "OR";

        $playlistItemVersionListQueryFields = [
            'playlist_item_version.id',
            'playlist_item_version.current_review_code',
            'playlist_item_version.playlist_version_id',
            'playlist_item_version.playlist_package_id',
            'playlist_item_version.playlist_id',
            'playlist_item_version.playlist_item_id',
            'playlist_item_version.entity_id',
            'playlist_item_version.review_request_id',
            'playlist_item_version.version_id',
            'playlist_item_version.task_id',
            'playlist_item_version.sort_index',
            'playlist_item_version.status',
            'playlist_item_version.created',
            'playlist_item_version.created_by',
            'playlist_item_version.deal_status',
            'playlist_item_version.tenant_id',

            'review_request_node.id',
            'review_request_node.review_request_id',
            'review_request_node.role_code',
            'review_request_node.parent_id',
            'review_request_node.plan_reviewer',
            'review_request_node.real_reviewer',
            'review_request_node.is_pass',
            'review_request_node.is_reviewed',
            'review_request_node.is_active',
            'review_request_node.created',
            'review_request_node.uuid',
            'review_request_node.reviewed',
            'review_request_node.param',
            'review_request_node.start_at',
            'review_request_node.is_terminate',
            'review_request_node.feedback_status',
            'review_request_node.is_second_confirm',
            'review_request_node.partyb_feedback_status'
        ];

        //只筛选出在当前进度的审核列

        $playlistItemVersionList = $this->playlistItemVersionModel
            ->alias('playlist_item_version')
            ->join("review_request_node ON review_request_node.review_request_id = playlist_item_version.review_request_id")
            ->where([$playlistVersionCurrentRoleFilter, 'review_request_node.is_active' => 'yes', "_logic" => "AND"])
            ->field(build_complex_query_fields($playlistItemVersionListQueryFields, '__'))
            ->select();
        $taskIdList = array_column($playlistItemVersionList, 'playlist_item_version__task_id', 'playlist_item_version__task_id');
        // 查询任务的关系map
        $mapData = $this->conversionInsideIdMap($taskIdList);
        $map = $mapData['a_to_b_map'] ?? [];
        // 通过 review_request_id 查询出 review_request_node_id
        $reviewRequestMap = [];
        $reviewRequestCurrentCode = [];
        foreach ($playlistItemVersionList as $index => &$item) {
            $tmpData = separate_complex_query_data($item, '__');
            $item = $tmpData['playlist_item_version'];

            // 如果是外包任务 那么替换task_id为乙方任务id (审片室都是真正的任务id)
            if (isset($map[$item['task_id']])) {
                $item['task_id'] = $map[$item['task_id']];
            }

            if (!empty($tmpData['review_request_node']) && !empty($tmpData['review_request_node']['id'])) {
                if ($tmpData['review_request_node']['is_terminate'] === 'no'
                    && $tmpData['review_request_node']['plan_reviewer'] === $getUserId) {
                    $item['review_request_node'] = $tmpData['review_request_node'];
                    $item['review_request_node_id'] = $tmpData['review_request_node']['id'];
                }
            }

            if (!empty($item['review_request_node']) && !isset($reviewRequestMap[$item['playlist_version_id']]) && $tmpData['review_request_node']['plan_reviewer'] === $getUserId) {
                $reviewRequestMap[$item['playlist_version_id']] = $item['review_request_id'];
                $reviewRequestCurrentCode[$item['review_request_id']] = $item['review_request_node']['role_code'];
            }
        }
        $playlistItemVersionList = array_group_by($playlistItemVersionList, 'playlist_version_id');

        //查询进度
        $reviewRequestNodeGroup = [];
        if (!empty($reviewRequestMap)) {
            $reviewRequestNodeList = model(ReviewRequestNodeModel::class)
                ->where(['review_request_id' => ["IN", join(",", $reviewRequestMap)]])->field("id,role_code,parent_id,plan_reviewer,review_request_id")->select();
            $reviewRequestNodeGroup = $this->dealReviewSchedule($reviewRequestNodeList, $reviewRequestCurrentCode);
        }

        if (!empty($playlistVersionStepIdList)) {
            $stepList = model(StepModel::class)->where(['id' => ['IN', $playlistVersionStepIdList]])->field('id,name')->select();
            $stepMap = array_column($stepList, 'name', 'id');
        }


        foreach ($playlistVersionList as &$item) {
            $item['children'] = $playlistItemVersionList[$item['id']] ?? [];
            $item['step_name'] = $stepMap[$item['step_id']] ?? "";
            $item['review_schedule'] = null;
            if (isset($reviewRequestMap[$item['id']]) && isset($reviewRequestNodeGroup[$reviewRequestMap[$item['id']]])) {
                $item['review_schedule'] = $reviewRequestNodeGroup[$reviewRequestMap[$item['id']]];
            }

        }
        return $playlistVersionList;
    }

    /**
     * 检查任务关联的播放列表提交状态
     * @param int $nodeId
     * @return array|null
     * @throws Exception|\Exception
     */
    public function checkTaskRelatedPlaylistCanSubmit(int $nodeId)
    {
        /**
         * 1. 更新当前任务关联的审核列表当前审核角色环节code
         *
         * 2. 更新当前任务关联的播放列表version状态
         *
         */


        $reviewRequestNode = model(ReviewRequestNodeModel::class)->find($nodeId);
        $playlistVersionIdList = $this->playlistItemVersionModel->where(['review_request_id' => $reviewRequestNode['review_request_id']])
            ->field('playlist_version_id')->group('playlist_version_id')->select();
        if (empty($playlistVersionIdList)) {
            return null;
        }
        //审核节点流程
        $reviewRequestNodeFlow = model(ReviewRequestNodeModel::class)->where(['review_request_id' => $reviewRequestNode['review_request_id']])->field('role_code')->select();
        $roleCodeFlow = array_column($reviewRequestNodeFlow, 'role_code');

        $playlistVersionIdList = array_column($playlistVersionIdList, 'playlist_version_id', 'playlist_version_id');
        $playlistVersionList = $this->playlistVersionModel->where(['id' => ['IN', $playlistVersionIdList]])->field('id,current_review_code')->select();
        $playlistVersionList = array_column($playlistVersionList, 'current_review_code', 'id');

        $latestPlaylistItemVersionList = $this->playlistItemVersionModel
            ->where(['playlist_version_id' => ['IN', $playlistVersionIdList]])->field('playlist_version_id,review_request_id')->select();

        if (!empty($latestPlaylistItemVersionList)) {
            $latestPlaylistItemVersionList = array_group_by($latestPlaylistItemVersionList, 'playlist_version_id');
        }

        $playlistVersionUpdateDataList = [];
        foreach ($latestPlaylistItemVersionList as $playlistVersionId => $currentLatestPlaylistItemVersionList) {
            // 检查有没有提交过播放列表审核记录
            if (!isset($playlistVersionList[$playlistVersionId])) {
                break;
            }
            $currentReviewCode = $playlistVersionList[$playlistVersionId];

            $currentReviewRequestIds = array_column($currentLatestPlaylistItemVersionList, 'review_request_id');
            // 需要判断是否以全部二次确认
            // 存在提交记录 检查是否已经全部审核完
            $notReviewedReviewRequestCount = $this->reviewRequestNodeModel
                ->where(['review_request_id' => ['IN', implode(',', $currentReviewRequestIds)], 'is_second_confirm' => 'no'])->find();
            if (empty($notReviewedReviewRequestCount)) {
                // 已经审核完 修改最后一个版本的审核信息未已结束
                $playlistVersionUpdateDataList[] = ['id' => $playlistVersionId, 'current_review_code' => 'done', 'status' => 'review_done', 'end_time' => time(),];
            } else {
                // 没有审核完 那么检查是否需要修改 current_review_code
                $allReviewedReviewRequestCount = $this->reviewRequestNodeModel
                    ->where(['review_request_id' => ['IN', $currentReviewRequestIds], 'role_code' => $currentReviewCode, 'is_second_confirm' => 'no'])->find();
                //当前角色审核列表所有的子项是否通过
                $allNotReviewedReviewRequestCount = $this->reviewRequestNodeModel->where([
                    'review_request_id' => ['IN', $currentReviewRequestIds],
                    'role_code' => $currentReviewCode,
                    'is_second_confirm' => 'yes',
                    'is_pass' => 'yes'
                ])->find();

                //如果都进行了二次确认,且只要有一个通过了,此流程就能往下进行
                if (empty($allReviewedReviewRequestCount)) {
                    if (!empty($allNotReviewedReviewRequestCount)) {
                        //获取下一个审核人物的角色
                        $roleCodeIndex = array_search($currentReviewCode, $roleCodeFlow);
                        $roleCodeIndex = $roleCodeIndex + 1;
                        $currentNextReviewCode = $currentReviewCode; //如果没有下一个节点,默认则是当前节点(也就是最后一个)
                        if ($roleCodeIndex !== count($roleCodeFlow)) { //判断是不是最后一个,如果不是获取下一个节点
                            $currentNextReviewCode = $roleCodeFlow[$roleCodeIndex];
                        }

                        $playlistVersionUpdateDataList[] = [
                            'id' => $playlistVersionId,
                            'current_review_code' => $currentNextReviewCode,
                            'current_schedule_code' => $currentNextReviewCode,
                        ];
                    } else { //如果都不通过 ，则流程结束
                        $playlistVersionUpdateDataList[] = [
                            'id' => $playlistVersionId,
                            'current_review_code' => 'done',
                            'end_time' => time(),
                            'status' => 'review_done',
                        ];
                    }
                }
            }
        }
        $res = [];
        $reviewDonePlaylistIds = [];
        // 更新审核进度数据
        foreach ($playlistVersionUpdateDataList as $playlistVersion) {
            $playlistVersionSave = $this->playlistVersionModel->modifyItem($playlistVersion);
            $res[] = $playlistVersionSave;
            if (!empty($playlistVersionSave)) {
                if ($playlistVersionSave['status'] === 'review_done') {
                    $reviewDonePlaylistIds[] = $playlistVersionSave['id'];
                }
            }
        }
        //将剩余未完成的playlist_item修改为以完成
        if (!empty($reviewDonePlaylistIds)) {
            $unReviewDonePlaylistItemVersion = $this->playlistItemVersionModel
                ->where(['playlist_version_id' => ['IN', $reviewDonePlaylistIds], 'status' => ['IN', 'review_done,reviewing']])->field('id')->select();
            if (!empty($unReviewDonePlaylistItemVersion)) {
                $unReviewDonePlaylistItemVersionIds = array_column($unReviewDonePlaylistItemVersion, 'id');
                $this->playlistItemVersionModel->where(['id' => ['IN', $unReviewDonePlaylistItemVersionIds]])->save(['status' => 'review_done']);
            }
        }


        return $res;
    }

    /**
     * 检查状态变化
     * @param int $nodeId
     * @param array $version
     * @return int|null
     * @throws \Exception
     */
    public function checkReviewNeedHandleStatus(int $nodeId, array $version)
    {
        $reviewRequestNode = $this->reviewRequestNodeModel->where(['id' => $nodeId])->find();
        if (empty($reviewRequestNode)) {
            return null;
        }
        $isCheckRoleCodeReview = $reviewRequestNode['role_code'] === $this->getCheckRoleCode();
        trace('角色判断进入' . $isCheckRoleCodeReview, 'DEBUG');

        if ($reviewRequestNode['is_pass'] === 'no') {
            // 审核通过

            $task = $this->taskModel->field('id,deal_status')->find($version['link_id']);
            if ($task['deal_status'] === 'submitted') {
                // 处于制片未提交的状态下

                $reviewRequest = model(ReviewRequestModel::class)->find($reviewRequestNode['review_request_id']);
                $isPartyAReview = $version['tenant_id'] !== $reviewRequest['tenant_id'];
                if ($isPartyAReview) {
                    // 是外包任务甲方审核
                    $orderService = OrderService::getInstance();
                    $orderTaskListItem = $orderService->getOrderTaskListItemByRealTaskId($version['link_id']);
                    if (!empty($orderTaskListItem)) {
                        trace('更新外包任务列表Item审核状态为 pending' . $version['link_id'], 'DEBUG');
                        model(OrderTaskListModel::class)->save(['id' => $orderTaskListItem['id'], 'deal_status' => 'pending']);
                    } else {
                        trace('找不到外包任务列表Item 外包任务ID' . $version['link_id'], 'ERR');
                    }
                }
            }
        } else {
            if ($isCheckRoleCodeReview) {
                // 是组长审核
                $nextChildrenNode = $this->reviewRequestNodeModel->where(['parent_id' => $nodeId])->field('id')->find();
                if (!empty($nextChildrenNode)) {
                    model(ReviewRequestNodeModel::class)->modifyItem(['id' => $nextChildrenNode['id'], 'is_active' => 'no', 'start_at' => 0]);
                    $reviewRequest = model(ReviewRequestModel::class)->find($reviewRequestNode['review_request_id']);
                    // 更新任务的审核状态
                    /**
                     * 判断任务的类型 是不是外包任务
                     * 1. 内部任务审核直接修改任务的审核状态
                     * 2. 外部任务审核查询原始任务 修改任务的审核状态
                     */
                    $isPartyAReview = $version['tenant_id'] !== $reviewRequest['tenant_id'];
                    $updateTaskId = $version['link_id'];
                    if ($isPartyAReview) {
                        $orderService = OrderService::getInstance();
                        $sourceTask = $orderService->getSourceTaskByTaskId($version['link_id']);
                        if (!empty($sourceTask)) {
                            trace('更新外包原始任务审核状态为 to_submit' . $version['link_id'], 'DEBUG');
                            $updateTaskId = $sourceTask['id'];
                            model(TaskModel::class)->save(['id' => $sourceTask['id'], 'deal_status' => 'to_submit']);
                        } else {
                            trace('找不到外包任务的原始任务 外包任务ID' . $version['link_id'], 'ERR');
                        }
                    } else {
                        trace('更新任务审核状态为 to_submit' . $version['link_id'], 'DEBUG');
                        model(TaskModel::class)->save(['id' => $version['link_id'], 'deal_status' => 'to_submit']);
                    }

                    $this->reviewRequestModel->where(['id' => $reviewRequestNode['review_request_id']])->save(['need_handle' => 'yes']);

                    // 组长审核完，增加未处理数据记录
                    if ($updateTaskId > 0) {
                        // $updateTaskId，哪方审核就用哪方的任务id
                        Client::send('count_pending', build_queue_data_with_xu([
                            'type' => 'review_submit',
                            'mode' => 'add',
                            'data' => ["id" => $updateTaskId]
                        ]));
                    }

                    return 1;
                }
            }
        }


        return 0;
    }

    /**
     * 批量审核任务
     * @param int $playlistVersionId
     * @param bool $isPass
     * @param int $userId
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function reviewAllByPlaylistVersion(int $playlistVersionId, bool $isPass, int $userId)
    {
        $myUserInfo = LoginService::getInstance()->getUserInfo($userId, false);
        $roleCode = $myUserInfo['role']['code'] ?? '';
        $playlistVersion = $this->playlistVersionModel->find($playlistVersionId);
        if (empty($playlistVersion)) {
            throw new LogicException('playlist version not found', ErrorCode::DATA_INVALID);
        }
        // 查询出待我这个角色审核的审核节点
        $needMeReviewReviewRequestNodes = $this->playlistVersionModel
            ->alias('pv')
            ->join('playlist_item_version piv on pv.id = piv.playlist_item_id')
            ->join('review_request_node rrn ON rrn.review_request_id = piv.review_request_id')
            ->join('review_request rr on  rr.id = rrn.review_request_id')
            ->where([
                'rr.is_reviewed' => 'no',
                'rrn.is_reviewed' => 'no',
                'rrn.is_active' => 'yes',
                'rrn.role_code' => $roleCode,
                'pv.id' => $playlistVersionId,
                'pv.current_review_code' => $roleCode,
            ])
            ->field('rrn.id')
            ->select();

        $res = [];
        $reviewRequestService = ReviewRequestService::getInstance();
        foreach ($needMeReviewReviewRequestNodes as $node) {
            $res[] = $reviewRequestService->review([
                'id' => $node['id'],
                'is_pass' => $isPass ? 'yes' : 'no'
            ], $userId);
        }

        // 当一个播放列表全部审核完 那么就更新下环节code
        $nextRoleCode = $this->getNextReviewRoleCode($playlistVersion['step_id'], $roleCode);
        // 通过的话 修改下个审核环节role_code
        if ($isPass) {
            // 如果没有下个审核环节了 就改为done
            if (empty($nextRoleCode)) {
                $nextRoleCode = 'done';
            }
            $this->playlistVersionModel->modifyItem(['id' => $playlistVersionId, 'current_review_code' => $nextRoleCode]);
        } else {
            // 不通过 那么就修改为
            $this->playlistVersionModel->modifyItem(['id' => $playlistVersionId, 'current_review_code' => 'done']);
        }
        return $res;
    }

    /**
     * 查询对比的任务版本数据
     * @param $taskId
     * @return array
     */
    public function getCompareDataSource($taskId)
    {
        $currentTask = $this->taskModel->find($taskId);
        if (empty($currentTask)) {
            throw new LogicException('task not found', ErrorCode::TASK_NOT_FOUND);
        }

        $taskFilter = [
            'entity_id' => $currentTask['entity_id'],
            'step_type' => 'step',
        ];
        $taskList = $this->taskModel->where($taskFilter)->field('id,name,code')->select();

        $taskIdList = array_column($taskList, 'id');
        $taskIdListExceptCurrentTask = array_filter($taskIdList, function ($item) use ($taskId) {
            return $item != $taskId;
        });

        $maxVersionListExceptCurrentTask = [];
        if (count($taskIdListExceptCurrentTask) > 0) {
            $versionListExceptCurrentTaskFilter = [
                'module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
                'link_id' => ['IN', $taskIdListExceptCurrentTask]
            ];
            $maxVersionIdListExceptCurrentTask = $this->versionModel->where($versionListExceptCurrentTaskFilter)->field('max(id) as id')->group('link_id')->select();
            $maxVersionIdListExceptCurrentTask = array_column($maxVersionIdListExceptCurrentTask, 'id');
            if (count($maxVersionIdListExceptCurrentTask)) {
                $maxVersionListExceptCurrentTaskFilter = [
                    'id' => ['IN', $maxVersionIdListExceptCurrentTask]
                ];
                $maxVersionListExceptCurrentTask = $this->versionModel->where($maxVersionListExceptCurrentTaskFilter)->select();
            }
        }
        $versionListCurrentTaskFilter = [
            'module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
            'link_id' => $taskId
        ];
        $versionListCurrentTask = $this->versionModel->where($versionListCurrentTaskFilter)->select();
        $versionList = array_merge($maxVersionListExceptCurrentTask, $versionListCurrentTask);
        $versionMediaIdList = [];
        $versionList = array_map(function ($version) use (&$versionMediaIdList) {
            $paramFields = json_decode($version['param'], true);
            $version['param'] = $paramFields;
            $jsonFields = json_decode($version['json'], true);
            $jsonFields['version_media'] = $jsonFields['version_media'] ?? '[]';
            $jsonFields['version_media'] = explode(',', $jsonFields['version_media']);
            foreach ($jsonFields['version_media'] as $mediaId) {
                if (intval($mediaId) > 0 && !in_array($mediaId, $versionMediaIdList)) {
                    $versionMediaIdList[] = $mediaId;
                }
            }
            return array_merge($version, $jsonFields);
        }, $versionList);
        $mediaList = [];
        if (count($versionMediaIdList)) {
            $mediaList = model(MediaModel::class)->where(['id' => ['IN', $versionMediaIdList]])->select();
            $mediaList = array_map(function ($item) {
                return CommonService::getFormatAttrData(model(MediaModel::class), $item);
            }, $mediaList);
            $mediaList = array_column($mediaList, null, 'id');
        }

        if (count($versionList)) {
            $versionList = array_group_by($versionList, 'link_id');
        }

        foreach ($taskList as &$task) {
            $task['children'] = $versionList[$task['id']] ?? [];
            foreach ($task['children'] as &$version) {
                $tmpMedia = [];
                foreach ($version['version_media'] as $mediaId) {
                    $mediaId = $mediaList[$mediaId] ?? null;
                    if (!empty($mediaId)) {
                        $tmpMedia[] = $mediaId;
                    }
                }
                $version['version_media'] = $tmpMedia;
            }
        }
        return $taskList;
    }

    /**
     * 修复之前任务的处理状态
     * @return array
     * @throws Throwable
     */
    public function syncTaskDealStatus()
    {
        $taskModuleId = Module::$moduleDictData['module_index_by_code']['task']['id'];
        $maxVersionId = model(TaskModel::class)
            ->join("version on version.link_id = task.id and version.module_id = {$taskModuleId}", 'LEFT')
            ->where("version.id is not null")
            ->field('max(version.id) as version_id')
            ->group('task.id')
            ->select();


        $maxVersionId = array_column($maxVersionId, 'version_id');

        $version = model(VersionModel::class)->where(['id' => ['IN', $maxVersionId]])->select();


        $isPassVersion = array_filter($version, function ($versionItem) {
            return $versionItem['is_pass'] == 'yes';
        });

        $notPassVersion = array_filter($version, function ($versionItem) {
            return $versionItem['is_pass'] == 'no';
        });

        $notPassVersionId = array_column($notPassVersion, 'id');
        $notPassVersionReviewRequest = model(ReviewRequestModel::class)
            ->where(['link_id' => ['IN', $notPassVersionId], 'module_id' => Module::$moduleDictData['module_index_by_code']['version']['id']])
            ->select();

        //未通过的需要判断
        // 判断是否组长提交 need_handle (yes 需要继续判断 , no 为 no_submit)
        // 判断是否制片提交了审核版本 play_list_item_version中是否有数据 需要通过任务判断 没有则是  待提交状态 ,有则是以提交
        $isNeedHandleItem = array_filter($notPassVersionReviewRequest, function ($notPassVersionReviewRequestItem) {
            return $notPassVersionReviewRequestItem['need_handle'] === 'yes';
        });

        $isNeedHandleItemVersionId = array_column($isNeedHandleItem, 'link_id');
        $isNeedHandleItemTask = model(VersionModel::class)->where(['id' => ['IN', $isNeedHandleItemVersionId]])->select();
        $isNeedHandleItemTaskId = array_column($isNeedHandleItemTask, 'link_id');

        $playlistItemVersionList = $this->playlistItemVersionModel->where([
            'task_id' => ['IN', $isNeedHandleItemTaskId]
        ])->select();
        //获取以提交的
        $playlistItemVersionIds = array_column($playlistItemVersionList, 'task_id', 'task_id');
        //比对出制片没有提交的
        $isSubmitted = array_diff($isNeedHandleItemTaskId, $playlistItemVersionIds);

        //通过的,去修改为以处理
        $isPassVersionLinkIds = array_column($isPassVersion, 'link_id');
        $taskModel = model(TaskModel::class);
        $taskModel->startTrans();
        try {
            $isSubmittedTask = $taskModel->where(['id' => ['IN', $isSubmitted]])->save(['deal_status' => 'to_submit']);
            $playlistItemVersionIdsTask = $taskModel->where(['id' => ['IN', $playlistItemVersionIds]])->save(['deal_status' => 'submitted']);
            $isPassVersionLinkIdsTask = $taskModel->where(['id' => ['IN', $isPassVersionLinkIds]])->save(['deal_status' => 'processed']);
            $taskModel->commit();
        } catch (Throwable $e) {
            $taskModel->rollback();
            throw $e;
        }
        $res = [
            'isSubmittedTask' => $isSubmittedTask,
            'playlistItemVersionIdsTask' => $playlistItemVersionIdsTask,
            'isPassVersionLinkIdsTask' => $isPassVersionLinkIdsTask,
        ];
        return $res;
    }

    /**
     * 获取审核列表
     * @param $param
     * @param $currentTenantId
     * @param $userId
     * @return array
     * @throws \Exception
     */
    public function getTaskSubmitReview($param, $currentTenantId, $userId)
    {
        $page = $param['page'] ?? [1, C('default_page_total')];
        $stepCategoryId = $param['filter']['step_category_id'] ?? [];
        $filter = $param['filter'] ?? [];
        $taskWorkOrderService = TaskWorkOrderService::getInstance();
        $statusData = array_column(model(StatusModel::class)->select(), 'id', 'code');
        $module = [];
        if (!empty($stepCategoryId)) {
            $module = $taskWorkOrderService->getModuleByStepCategoryId($stepCategoryId);
        }

        if (!isset($filter['project_id'])) {
            $projectList = ProjectService::getInstance()->getUserProjectList($userId, ['param' => ['project_status' => 'inprogress']]);
            $projectIds = array_column(array_column($projectList['rows'], 'project'), 'id');
            if (!empty($projectIds)) {
                $filter['project_id'] = ["IN", $projectIds];
            }
        }

        $filter = $taskWorkOrderService->parseMultipleEntityTaskFilter($filter);
        $filter['task.step_type'] = 'step';
        if (!empty($module)) {
            $filter['entity.module_id'] = $module['id'];
        }


        $filter["json_extract(entity.json, concat('$.', module.code,'_status'))"] = ['NEQ', $statusData['closed']];

        $taskFiled = ['task.id', 'task.executor', 'task.plan_end_time', 'task.deal_status', 'task.plan_end_time',
            'task.plan_start_time', 'task.executor_tenant_id', 'task.executor', 'task.tenant_id', 'task.name as step_name',
            'entity.entity_id as entity_entity_id', 'entity.id as entity_id', 'entity.name as entity_name', 'entity.initial_episode_code', 'entity.showings_number',
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category", "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade"
        ];

        $taskIdList = model(TaskModel::class)
            ->join("entity on entity.id = task.entity_id")
            ->join("module on module.id = entity.module_id")
            ->join("task_work_order on task_work_order.type = 'task_making' and task_work_order.task_id = task.id", "LEFT")
            ->join("task_clock on task_clock.task_id = task.id", "LEFT")
            ->where($filter)->group('task.id')->field('task.id')->page($page[0], $page[1])->select();

        $taskList = [];
        if (!empty($taskIdList)) {
            $taskIds = array_column($taskIdList, 'id');

            $taskList = model(TaskModel::class)
                ->join("entity on entity.id = task.entity_id")
                ->join("module on module.id = entity.module_id")
                ->where(['task.id' => ['IN', $taskIds]])
                ->field($taskFiled)->select();

            // 区分外包任务
            $outsideTaskList = [];
            $insideTaskList = [];
            $outsideSupplierTenantId = [];
            $executorUserIdList = [];
            $parentEntityIdList = [];
            $taskIds = [];
            foreach ($taskList as &$taskData) {
                $taskData['is_outside'] = false;
                $taskIds[$taskData['id']] = $taskData['id'];

                if ($taskData['entity_entity_id'] > 0 && !in_array($taskData['entity_entity_id'], $parentEntityIdList)) {
                    $parentEntityIdList[] = $taskData['entity_entity_id'];
                }

                if ($taskData['executor_tenant_id'] != 0 && $taskData['executor_tenant_id'] != $taskData['tenant_id']) {
                    $outsideTaskList[$taskData['id']] = $taskData;
                    $outsideSupplierTenantId[$taskData['executor_tenant_id']] = $taskData['executor_tenant_id'];
                    $taskData['is_outside'] = true;
                } else {
                    $insideTaskList[$taskData['id']] = $taskData;
                    if ($taskData['executor'] > 0) {
                        $executorUserIdList[$taskData['executor']] = $taskData['executor'];
                    }
                }
            }


            $insideTaskIds = array_column($insideTaskList, 'id', 'id');
            $outsideTaskIdMap = [];
            $outTaskIds = [];
            if (!empty($outsideTaskList)) {
                // 通过订单查询外包任务真实数据
                $orderService = OrderService::getInstance();
                $outsideTaskIdMap = $orderService->getOutsideTaskListByTaskIdList(array_column($outsideTaskList, 'id'));
                $outTaskIds = $insideTaskIds + array_column($outsideTaskIdMap, 'id', 'id');
            }


            //提交次数
            $versionMap = $this->getMaxVersionMap($outTaskIds);
            //工单状态
            $taskWorkOrderService = TaskWorkOrderService::getInstance();
            $taskWorkOrderMap = $taskWorkOrderService->getMaxTaskWorkMap($taskIds);

            $parentList = [];
            if ($parentEntityIdList) {
                $parentList = model(EntityModel::class)->join("module on module.id = entity.module_id")
                    ->where(['entity.id' => ['IN', join(',', $parentEntityIdList)]])->field("entity.id,entity.name,module.code as module_code")->select();
                $parentList = array_column($parentList, null, 'id');
            }

            //执行人查询
            $taskService = TaskService::getInstance();
            $supplierRes = $taskService->queryTaskSupplierInfo($currentTenantId, [], array_values($outsideSupplierTenantId), [], array_values($executorUserIdList));


            //闹钟个数
            $taskClock = model(TaskClockModel::class)->where(['task_id' => ["IN", $taskIds]])->field('task_id,id,time')->order('time asc')->select();
            $currentTime = time();
            $taskClockCount = [];
            $taskClockList = [];
            $taskRecentClock = [];
            foreach ($taskClock as $taskClockItem) {
                if (isset($taskClockCount[$taskClockItem['task_id']])) {
                    ++$taskClockCount[$taskClockItem['task_id']];
                } else {
                    $taskClockCount[$taskClockItem['task_id']] = 1;
                }

                if (isset($taskClockList[$taskClockItem['task_id']])) {
                    $taskClockList[$taskClockItem['task_id']][] = $taskClockItem;
                } else {
                    $taskClockList[$taskClockItem['task_id']] = [$taskClockItem];
                }

                if (!isset($taskRecentClock[$taskClockItem['task_id']]) && $taskClockItem['time'] > $currentTime) {
                    $taskRecentClock[$taskClockItem['task_id']] = $taskClockItem['time'];
                }
            }

            //判断是否能勾选
            //资产 以提交且处理中的任务

            $dataFormatCallback = function ($item) use ($versionMap, $taskWorkOrderMap, $supplierRes, $taskClockCount, $outsideTaskIdMap, $taskClockList, $taskRecentClock, $parentList) {
                $item['task_work_order_type'] = 'task_making';
                $taskId = $item['id'];
                if ($item['is_outside']) {
                    $taskId = $outsideTaskIdMap[$taskId]['id'] ?? 0;
                }
                $item['submit_count'] = $versionMap[$taskId]['number'] ?? null;
                $item['version_id'] = $versionMap[$taskId]['id'] ?? 0;
                $item['task_work_order_status'] = $taskWorkOrderMap[$item['id']]['status'] ?? null;
                $item['executor_name'] = "";
                if ($item['executor_tenant_id'] > 0 && $item['executor_tenant_id'] != $item['tenant_id']) {
                    $item['executor_name'] = $supplierRes['outside'][$item['executor_tenant_id']]['name'] ?? "";
                } elseif ($item['executor'] > 0) {
                    $item['executor_name'] = $supplierRes['executor'][$item['executor']]['name'] ?? "";
                }
                $item['clock_count'] = $taskClockCount[$item['id']] ?? 0;
                $item['task_clock'] = $taskClockList[$item['id']] ?? [];
                $item['recent_clock_time'] = $taskRecentClock[$item['id']] ?? 0;

                if ($item['entity_entity_id'] > 0 && isset($parentList[$item['entity_entity_id']])) {
                    $item[$parentList[$item['entity_entity_id']]["module_code"]] = $parentList[$item['entity_entity_id']]['name'];
                }

                return $item;
            };
            $taskList = array_map($dataFormatCallback, $taskList);
        }
        return $taskList;
    }

    /**
     * 获取已提交审核任务
     * @param $param
     * @param $tenantId
     * @param $userId
     * @return array|false|mixed|string
     * @throws \Exception
     */
    public function getAssetSubmittedReviewTask($param, $tenantId, $userId)
    {
        $page = $param['page'] ?? [1, C('default_page_total')];
        $stepCategoryId = $param['filter']['step_category_id'] ?? [];
        $taskWorkOrderService = TaskWorkOrderService::getInstance();
        $isFilterOverdue = $param['filter']['is_filter_overdue'] ?? false;
        if (!empty($stepCategoryId)) {
            $module = $taskWorkOrderService->getModuleByStepCategoryId($stepCategoryId);
            $param['filter']['entity.module_id'] = $module['id'];
            $param['filter']['playlist_version.step_category_id'] = $stepCategoryId;
        }

        $filter = $param['filter'] ?? [];
        if (!isset($filter['project_id'])) {
            $projectList = ProjectService::getInstance()->getUserProjectList($userId, ['param' => ['project_status' => 'inprogress']]);
            $projectIds = array_column(array_column($projectList['rows'], 'project'), 'id');
            if (!empty($projectIds)) {
                $filter['project_id'] = ["IN", $projectIds];
            }
        }

        $filter = $taskWorkOrderService->parseMultipleEntityTaskFilter($filter);
        $filter['task.step_type'] = 'step';
        $filter['playlist_version.tenant_id'] = $tenantId;

        //逾期筛选
        if ($isFilterOverdue) {
            $filter[] = [
                'playlist_version.status' => ['NEQ', 'review_done'],
                '_string' => "playlist_version.plan_end_time > 0 and playlist_version.plan_end_time <= " . time(),
            ];
        }

        $playlistVersionFields = ["playlist_version_id", "playlist_version.name", "playlist_version.status as playlist_version_status",
            "playlist_version.plan_end_time", "playlist_version.end_time", "playlist_version.step_category_id"];
        $playlistVersion = model(PlaylistVersionModel::class)
            ->join("playlist_item_version on playlist_item_version.playlist_version_id = playlist_version.id", 'LEFT')
            ->join("entity on playlist_item_version.entity_id = entity.id")
            ->join("task on playlist_item_version.task_id = task.id")
            ->where($filter)
            ->field($playlistVersionFields)
            ->group('playlist_version_id')
            ->page($page[0], $page[1])
            ->select();

        return !empty($playlistVersion) ? $playlistVersion : [];
    }


    /**
     * 获取资产已提交审核列表的子项
     * @param $param
     * @param $currentTenantId
     * @param $userId
     * @return array
     * @throws \Exception
     */
    public function getAssetSubmittedReviewPlaylistItem($param, $currentTenantId, $userId)
    {
        $filter = $param['filter'];
        $page = $param['page'] ?? [1, C("database.database_max_select_rows")];
        $playlistVersionId = $filter['playlist_version_id'];
        $stepCategoryId = $param['filter']['step_category_id'];
        $dealStatus = $param['filter']['deal_status'] ?? [];

        $taskWorkOrderService = TaskWorkOrderService::getInstance();
        $module = $taskWorkOrderService->getModuleByStepCategoryId($stepCategoryId);
        unset($filter['step_category_id']);
        $playlistItemVersionFilter = [
            'playlist_version_id' => $playlistVersionId,
        ];
        if (!empty($dealStatus)) {
            // 处理状态过滤条件
            $playlistItemVersionFilter['deal_status'] = $dealStatus;
        }

        // 获取指定任务版本播放列表项数据
        $playlistItemVersion = model(PlaylistItemVersionModel::class)
            ->join('entity on entity.id = playlist_item_version.entity_id', 'LEFT')
            ->where($filter)
            ->page($page[0], $page[1])
            ->field('playlist_item_version.id,playlist_item_version.review_request_id,playlist_item_version.version_id,
            playlist_item_version.current_review_code,playlist_item_version.deal_status,playlist_item_version.entity_id,playlist_item_version.task_id')
            ->select();

        // 单次循环获取 versionIds、reviewRequestIds、entityIds、taskIds，利用index去重
        $versionIds = [];
        $reviewRequestIds = [];
        $entityIds = [];
        $taskIds = [];
        $reviewRequestRoleCodeMap = [];

        foreach ($playlistItemVersion as $playlistItemVersionItem) {
            if (!empty($playlistItemVersionItem['version_id'])) {
                $versionIds[$playlistItemVersionItem['version_id']] = $playlistItemVersionItem['version_id'];
            }
            if (!empty($playlistItemVersionItem['review_request_id'])) {
                $reviewRequestIds[$playlistItemVersionItem['review_request_id']] = $playlistItemVersionItem['review_request_id'];
            }
            $entityIds[$playlistItemVersionItem['entity_id']] = $playlistItemVersionItem['entity_id'];
            $taskIds[$playlistItemVersionItem['task_id']] = $playlistItemVersionItem['task_id'];
            $reviewRequestRoleCodeMap[$playlistItemVersionItem['review_request_id']] = $playlistItemVersionItem['current_review_code'];
        }

        //任务名信息
        $entityMap = [];
        $sequenceList = [];
        if (!empty($entityIds)) {
            $entityList = $this->entityModel->where(['id' => ["IN", $entityIds]])->field('id,name,initial_episode_code,showings_number,entity_id')->select();
            $entityMap = array_column($entityList, null, 'id');
            if ($module['code'] === 'shot') {
                $parentEntityIdList = array_column($entityMap, 'entity_id');
                $sequenceList = $taskWorkOrderService->getEntityListMap($parentEntityIdList);
            }
        }

        //任务信息
        $isWorkOrderTaskIds = [];
        $supplierRes = [];
        $taskMap = [];
        $taskWorkOrderReviewRequestNodeIds = [];
        $partyABTaskMap = [];
        if (!empty($taskIds)) {
            //查询外包任务id
            $partyATaskMap = $this->conversionInsideIdMap($taskIds);
            $partyABTaskMap = $partyATaskMap['a_to_b_map'];

            $taskList = model(TaskModel::class)->where(['id' => ['IN', $taskIds]])->field('id,name,executor,executor_tenant_id,tenant_id')->select();
            $taskMap = array_column($taskList, null, 'id');
            $outsideSupplierTenantId = [];
            $executorUserIdList = [];
            //执行人
            foreach ($taskList as $taskItem) {
                if ($taskItem['executor_tenant_id'] > 0 && $taskItem['executor_tenant_id'] != $currentTenantId) {
                    $outsideSupplierTenantId[$taskItem['executor_tenant_id']] = $taskItem['executor_tenant_id'];
                } else if ($taskItem['executor'] > 0) {
                    $executorUserIdList[$taskItem['executor']] = $taskItem['executor'];
                }
            }
            //执行人查询
            $taskService = TaskService::getInstance();
            $supplierRes = $taskService->queryTaskSupplierInfo($currentTenantId, [], array_values($outsideSupplierTenantId), [], array_values($executorUserIdList));

            //工单信息
            $taskWorkOrder = model(TaskWorkOrderModel::class)->where([
                'task_id' => ['IN', $taskIds],
                'type' => 'review_feedback'
            ])->field('review_request_node_id')->select();
            $taskWorkOrderReviewRequestNodeIds = array_column($taskWorkOrder, "review_request_node_id");
            $taskWorkOrderUserList = model(TaskWorkOrderModel::class)
                ->join("task_work_order_user on task_work_order_user.work_order_id = task_work_order.id")
                ->where(["task_work_order.task_id" => ["IN", $taskIds], "task_work_order_user.user_id" => $userId, 'task_work_order.type' => 'review_feedback'])->group("task_id")->field("task_id")->select();
            $isWorkOrderTaskIds = array_column($taskWorkOrderUserList, "task_id");
        }

        //1.填充版本信息
        $versions = [];
        if (!empty($versionIds)) {
            $versions = model(VersionModel::class)->where(['id' => ["IN", $versionIds]])->field('id,number')->select();
            $versions = array_column($versions, 'number', 'id');
        }

        //2.获取审核节点 补充进度字段 //通过playlist_version来确认当前审核人角色
        $reviewRequestFeedbackMap = [];
        $reviewRequestNodeGroup = [];

        if (!empty($reviewRequestIds)) {
            $reviewRequestNode = model(ReviewRequestNodeModel::class)->where([
                ['review_request_id' => ["IN", $reviewRequestIds]]
            ])->field('id,role_code,review_request_id,parent_id,plan_reviewer,real_reviewer,is_pass,is_reviewed,is_active,feedback_status,is_second_confirm')->select();


            $reviewRequestList = model(ReviewRequestModel::class)->where(['id' => ['IN', $reviewRequestIds]])
                ->field("id,JSON_UNQUOTE(JSON_EXTRACT(param, '$.review_deny_node_id')) as review_deny_node_id")->select();

            $reviewRequestMap = array_column($reviewRequestList, 'review_deny_node_id', 'id');

            //是否时当前审核点处理
            $currentReviewRequestNode = [];
            $reviewUserMap = [];
            foreach ($reviewRequestNode as &$reviewRequestNodeItem) {
                //如果实际完成人不为空,则填计划完成人
                if (!empty($reviewRequestNodeItem['real_reviewer'])) {
                    $reviewUserMap[$reviewRequestNodeItem['id']] = $reviewRequestNodeItem['real_reviewer'];
                } else {
                    $reviewUserMap[$reviewRequestNodeItem['id']] = $reviewRequestNodeItem['plan_reviewer'];
                }

                if (array_key_exists($reviewRequestNodeItem['review_request_id'], $reviewRequestRoleCodeMap) &&
                    $reviewRequestRoleCodeMap[$reviewRequestNodeItem['review_request_id']] === $reviewRequestNodeItem['role_code']) {
                    $currentReviewRequestNode[] = $reviewRequestNodeItem;
                }
            }
            //获取角色名字信息
            $roleCodes = array_unique(array_column($reviewRequestNode, 'role_code'));
            $roleNames = $this->getRoleName($roleCodes);
            $roleNames = array_column($roleNames, 'name', 'code');

            //审核人信息
            $reviewUserValues = array_values($reviewUserMap);
            $reviewUser = model(UserModel::class)->where(['id' => ['IN', $reviewUserValues]])->field('id,name')->select();
            $reviewUser = array_column($reviewUser, 'name', 'id');

            $reviewRequestNode = array_map(function ($reviewRequestNodeItem) use ($reviewRequestRoleCodeMap, $reviewUserMap, $reviewUser, $roleNames) {
                //补充审核人名字
                $reviewRequestNodeItem['reviewer_name'] = $reviewUser[$reviewUserMap[$reviewRequestNodeItem['id']]];
                //如果实际完成人不为空,则填计划完成人
                if (array_key_exists($reviewRequestNodeItem['review_request_id'], $reviewRequestRoleCodeMap) &&
                    $reviewRequestRoleCodeMap[$reviewRequestNodeItem['review_request_id']] === $reviewRequestNodeItem['role_code']) {
                    $reviewRequestNodeItem['is_current_review_node'] = 'yes';
                } else {
                    $reviewRequestNodeItem['is_current_review_node'] = 'no';
                }
                $reviewRequestNodeItem['role_name'] = $roleNames[$reviewRequestNodeItem['role_code']];
                return $reviewRequestNodeItem;
            }, $reviewRequestNode);

            //需要进行一次组内排序，以防节点排序出错
            $reviewRequestNodeGroup = array_group_by($reviewRequestNode, 'review_request_id');
            foreach ($reviewRequestNodeGroup as $reviewRequestId => $reviewRequestNodeGroupItem) {
                $reviewRequestNodeGroup[$reviewRequestId] = array_sort_by($reviewRequestNodeGroupItem, 'parent_id');
            }

            //当前审核节点的状态
            //3.填充是否有待确认反馈,反馈处理状态 (获取当前审核节点判断 , 判断是否通过)
            // 审核了 且通过 且反馈状态为等待确认反馈 则出现等待确认反馈状态为true
            foreach ($currentReviewRequestNode as $currentReviewRequestNodeItem) {
                // 默认状态 is_confirm_feedback 是否确认反馈、is_deal_feedback是否有待处理的反馈、feedback_status反馈状态、view_feedback查看反馈(是否存在反馈)
                $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['is_confirm_feedback'] = false;
                $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['is_deal_feedback'] = false;
                $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['feedback_status'] = "";
                $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['view_feedback'] = false;

                if ($currentReviewRequestNodeItem['feedback_status'] !== 'waiting_confirm') {
                    $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['feedback_status'] = $currentReviewRequestNodeItem['feedback_status'];
                }

                //判断是否审核 审核过 未通过 显示反馈， 以通过 判断 反馈状态不为待确认状态
                if ($currentReviewRequestNodeItem['is_reviewed'] === 'yes') {
                    if ($currentReviewRequestNodeItem['is_pass'] === 'yes') {
                        if ($currentReviewRequestNodeItem['feedback_status'] !== 'waiting_confirm') {
                            $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['view_feedback'] = true;
                        }
                    } else {
                        $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['view_feedback'] = true;
                        //当不同过时 且为等待确认状态
                        if ($currentReviewRequestNodeItem['feedback_status'] === 'waiting_confirm') {
                            $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['is_confirm_feedback'] = true;
                            //默认是出现反馈状态
                            $dealFeedback = true;
                            if (in_array($currentReviewRequestNodeItem['id'], $taskWorkOrderReviewRequestNodeIds)) { //如果存在工单则证明以环节制片以处理了
                                $dealFeedback = false;
                            }
                            $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['is_deal_feedback'] = $dealFeedback;
                        }
                    }

                    //如果没有二次确认且在review_request存在 deny 则不能再处理
                    if ($currentReviewRequestNodeItem['is_second_confirm'] == 'no'
                        && !empty($reviewRequestMap[$currentReviewRequestNodeItem['review_request_id']]) &&
                        $reviewRequestMap[$currentReviewRequestNodeItem['review_request_id']] == $currentReviewRequestNodeItem['id']) {
                        $reviewRequestFeedbackMap[$currentReviewRequestNodeItem['review_request_id']]['is_deal_feedback'] = false;
                    }
                }
            }


        }

        $dataFormatCallback = function ($item) use ($versions, $entityMap, $supplierRes, $isWorkOrderTaskIds, $reviewRequestFeedbackMap, $reviewRequestNodeGroup, $taskMap, $partyABTaskMap) {
            $item['task_work_order_type'] = 'review_feedback';
            $item['entity_name'] = $entityMap[$item['entity_id']]['name'] ?? "";
            $item['initial_episode_code'] = $entityMap[$item['entity_id']]['initial_episode_code'] ?? "";
            $item['showings_number'] = $entityMap[$item['entity_id']]['showings_number'] ?? "";
            $item['version_number'] = $versions[$item['version_id']] ?? null;
            $item['entity_entity_id'] = $entityMap[$item['entity_id']]['entity_id'] ?? 0;
            //执行人

            $item['executor_name'] = "";
            if ($taskMap[$item['task_id']]['executor_tenant_id'] > 0 && $taskMap[$item['task_id']]['executor_tenant_id'] != $taskMap[$item['task_id']]['tenant_id']) {
                $item['executor_name'] = $supplierRes['outside'][$taskMap[$item['task_id']]['executor_tenant_id']]['name'] ?? "";
            } elseif ($taskMap[$item['task_id']]['executor'] > 0) {
                $item['executor_name'] = $supplierRes['executor'][$taskMap[$item['task_id']]['executor']]['name'] ?? "";
            }
            $item['step_name'] = $taskMap[$item['task_id']]['name'];
            //进度
            $item['schedule'] = $reviewRequestNodeGroup[$item['review_request_id']] ?? [];
            //反馈处理结果 | 是否等待确认反馈
            $item['feedback_status'] = $reviewRequestFeedbackMap[$item['review_request_id']]['feedback_status'] ?? "";
            $item['is_confirm_feedback'] = $reviewRequestFeedbackMap[$item['review_request_id']]['is_confirm_feedback'] ?? false;
            $item['is_deal_feedback'] = $reviewRequestFeedbackMap[$item['review_request_id']]['is_deal_feedback'] ?? false;
            $item['view_feedback'] = $reviewRequestFeedbackMap[$item['review_request_id']]['view_feedback'] ?? false;
            //补充工单状态
            if (in_array($item['task_id'], $isWorkOrderTaskIds)) { //没有工单任务
                $item['is_task_work_order'] = 'yes';
            } else {
                $item['is_task_work_order'] = 'no';
            }
            //查看反馈时的id,如果有外包取出外包
            if (array_key_exists($item['task_id'], $partyABTaskMap)) {
                $item['feedback_task_id'] = $partyABTaskMap[$item['task_id']];
            } else {
                $item['feedback_task_id'] = $item['task_id'];
            }

            return $item;
        };

        if ($module['code'] === 'shot') {
            $dataFormatCallbackSub = $dataFormatCallback;
            $dataFormatCallback = function ($item) use (&$dataFormatCallbackSub, &$sequenceList) {
                $item = $dataFormatCallbackSub($item);
                $item['sequence'] = $sequenceList[$item['entity_entity_id']]['name'] ?? "";
                return $item;
            };
        }
        $playlistItemVersion = array_map($dataFormatCallback, $playlistItemVersion);

        return $playlistItemVersion;
    }

    /**
     * 内部接受反馈
     * @param $filter
     * @return array
     * @throws Throwable
     */
    public function acceptFeedback($filter)
    {
        $reviewRequestNodeId = $filter['review_request_node_id'];
        $playlistItemVersionId = $filter['id'];
        //相当于以前的拒绝审核 需要调用拒绝审核之后的处理
        $reviewRequestNode = $this->reviewRequestNodeModel->find($reviewRequestNodeId);
        $reviewRequest = $this->reviewRequestModel->find($reviewRequestNode['review_request_id']);

        //审核过的不能再审核
        if ($reviewRequest['is_reviewed'] === 'yes') {
            throw new LogicException("review request review done", ErrorCode::REVIEW_REQUEST_REVIEW_DONE);
        }

        ReviewRequestService::getInstance()->waitFeedbackDeal($reviewRequestNode);

        $playlistItemVersion = $this->playlistItemVersionModel->field('playlist_version_id')->find($playlistItemVersionId);
        if (empty($playlistItemVersion)) {
            return null;
        }
        return $this->playlistVersionModel->field('id as playlist_version_id,name,status as playlist_version_status,plan_end_time')->find($playlistItemVersion['playlist_version_id']);
    }


    /**
     * 更新老数据版本列表的进度
     * @return array
     * @throws \Exception
     */
    public function fixOldCurrentScheduleCodeInPlaylistVersion()
    {
        $playlistVersionList = $this->playlistVersionModel
            ->join('playlist_item_version on playlist_item_version.playlist_version_id = playlist_version.id')
            ->where(['playlist_version.current_review_code' => ['NEQ', 'done']])
            ->field('playlist_version.id,playlist_version.current_review_code,playlist_item_version.review_request_id,playlist_item_version.playlist_version_id')->select();


        $playlistReviewRequestMap = [];
        $reviewRequestIds = [];
        foreach ($playlistVersionList as $playlistVersionListItem) {
            if ($playlistVersionListItem['review_request_id'] !== 0) {
                if (!array_key_exists($playlistVersionListItem['playlist_version_id'], $playlistReviewRequestMap)) {
                    $playlistReviewRequestMap[$playlistVersionListItem['playlist_version_id']] = [$playlistVersionListItem['review_request_id']];
                } else {
                    $playlistReviewRequestMap[$playlistVersionListItem['playlist_version_id']][] = $playlistVersionListItem['review_request_id'];
                }
                $reviewRequestIds[] = $playlistVersionListItem['review_request_id'];
            }
        }

        if (!empty($reviewRequestIds)) {
            $reviewRequestList = model(ReviewRequestNodeModel::class)
                ->where(['review_request_id' => ['IN', $reviewRequestIds]])
                ->select();
            $reviewRequestGroup = array_group_by($reviewRequestList, 'review_request_id');
            $playlistVersionFixRoleCodeData = [];
            foreach ($playlistReviewRequestMap as $playlistVersionId => $playlistVersionGroup) {
                $minIndexRole = [];
                foreach ($playlistVersionGroup as $playlistVersionGroupItem) {
                    if (array_key_exists($playlistVersionGroupItem, $reviewRequestGroup)) {
                        foreach ($reviewRequestGroup[$playlistVersionGroupItem] as $index => $reviewRequestGroupPlayItem) {
                            if ($reviewRequestGroupPlayItem['is_active'] == 'yes') {
                                if (empty($minIndexRole)) {
                                    $minIndexRole = ['index' => $index, 'role_code' => $reviewRequestGroupPlayItem['role_code']];
                                } else {
                                    if ($index < $minIndexRole['index']) {
                                        $minIndexRole = ['index' => $index, 'role_code' => $reviewRequestGroupPlayItem['role_code']];
                                    }
                                }
                            }
                        }
                    }
                }

                if (!empty($minIndexRole)) {
                    $playlistVersionFixRoleCodeData[] = [
                        'id' => $playlistVersionId,
                        'current_review_code' => $minIndexRole['role_code'],
                        'current_schedule_code' => $minIndexRole['role_code']
                    ];
                }
                unset($minIndexRole);
            }
            foreach ($playlistVersionFixRoleCodeData as $playlistVersionFixRoleCodeDataItem) {
                model(PlaylistVersionModel::class)->save($playlistVersionFixRoleCodeDataItem);
            }

            return $playlistVersionFixRoleCodeData;
        }
    }


    /**
     * 修复当前进度角色
     * @return array
     * @throws \Exception
     */
    public function fixCurrentScheduleCodeInPlaylistVersion()
    {
        $playlistVersion = $this->playlistVersionModel->field('id,current_review_code')->select();

        //不为done则是当前角色
        $notDonePlaylistVersion = [];
        $donePlaylistVersion = [];
        $donePlaylistVersionIds = [];
        $notDonePlaylistVersionIds = [];
        $playlistVersionItemIds = [];
        foreach ($playlistVersion as $playlistVersionItem) {
            if ($playlistVersionItem['current_review_code'] != 'done') {
                $notDonePlaylistVersion[] = $playlistVersionItem;
                $notDonePlaylistVersionIds[] = $playlistVersionItem['id'];

            } else {
                $donePlaylistVersion[] = $playlistVersionItem;
                $donePlaylistVersionIds[] = $playlistVersionItem['id'];
            }
        }

        $notDonePlaylistVersionSaveData = [];
        $notDonePlaylistVersionCurrentReviewCodeMap = [];
        if (!empty($notDonePlaylistVersion)) {
            foreach ($notDonePlaylistVersion as $notDonePlaylistVersionItem) {
                $notDonePlaylistVersionSaveData[] = [
                    "id" => $notDonePlaylistVersionItem['id'],
                    "current_schedule_code" => $notDonePlaylistVersionItem['current_review_code'],
                    "status" => 'reviewing'
                ];
                $notDonePlaylistVersionCurrentReviewCodeMap[$notDonePlaylistVersionItem['id']] = $notDonePlaylistVersionItem['current_review_code'];
            }
            $this->playlistVersionModel->saveAll($notDonePlaylistVersionSaveData);
        }

        //为done则是最后一个角色
        $saveData = [];
        $donePlaylistVersionCurrentReviewCodeMap = [];
        if (!empty($donePlaylistVersion)) {
            $playlistItemVersionList = model(PlaylistItemVersionModel::class)->where([
                'playlist_version_id' => ["IN", $donePlaylistVersionIds]
            ])->select();

            $doneReviewRequestIds = [];
            $donePlaylistVersionReviewRequestMap = [];
            $donePlaylistItemVersionIds = [];
            $notSubmitPlaylistItemVersion = [];
            foreach ($playlistItemVersionList as $playlistItemVersionListItem) {
                if ($playlistItemVersionListItem['review_request_id'] !== 0 && !in_array($playlistItemVersionListItem['id'], $donePlaylistItemVersionIds)) {
                    $donePlaylistItemVersionIds[] = $playlistItemVersionListItem['id'];
                }
                if ($playlistItemVersionListItem['review_request_id'] == 0 && !in_array($playlistItemVersionListItem['id'], $notSubmitPlaylistItemVersion)) {
                    $notSubmitPlaylistItemVersion[] = $playlistItemVersionListItem['id'];
                }

                if ($playlistItemVersionListItem['review_request_id'] !== 0 && !in_array($playlistItemVersionListItem['review_request_id'], $doneReviewRequestIds)) {
                    $doneReviewRequestIds[] = $playlistItemVersionListItem['review_request_id'];
                }

                if ($playlistItemVersionListItem['review_request_id'] !== 0 &&
                    !array_key_exists($playlistItemVersionListItem['playlist_version_id'], $donePlaylistVersionReviewRequestMap)) {
                    $donePlaylistVersionReviewRequestMap[$playlistItemVersionListItem['playlist_version_id']] = $playlistItemVersionListItem['review_request_id'];
                }


            }

            //查询出每个review_request 最后一个review_request_node角色
            $reviewRequestList = model(ReviewRequestNodeModel::class)->where(['review_request_id' => ["IN", $doneReviewRequestIds]])
                ->field('review_request_id,max(id) as id')->group('review_request_id')->select();
            $reviewRequestNodeMap = array_column($reviewRequestList, 'id', 'review_request_id');
            $reviewRequestNodeIds = array_values($reviewRequestNodeMap);

            $reviewRequestNodes = model(ReviewRequestNodeModel::class)
                ->where(['id' => ["IN", $reviewRequestNodeIds]])->field('id,review_request_id,role_code')->select();
            $reviewRequestNodes = array_column($reviewRequestNodes, null, 'id');

            //填充每个playlist_version 最后一个review_request_node角色
            foreach ($donePlaylistVersionReviewRequestMap as $playlistVersionId => $donePlaylistVersionReviewRequestId) {
                if (array_key_exists($donePlaylistVersionReviewRequestId, $reviewRequestNodeMap)) {
                    $reviewRequestNodeMapReviewRequestId = $reviewRequestNodeMap[$donePlaylistVersionReviewRequestId];
                    if (array_key_exists($reviewRequestNodeMapReviewRequestId, $reviewRequestNodes)) {
                        $saveData[] = [
                            'id' => $playlistVersionId,
                            'current_schedule_code' => $reviewRequestNodes[$reviewRequestNodeMapReviewRequestId]['role_code']
                        ];
                        $donePlaylistVersionCurrentReviewCodeMap[$playlistVersionId] = $reviewRequestNodes[$reviewRequestNodeMapReviewRequestId]['role_code'];

                    }
                }
            }

            if (!empty($saveData)) {
                $this->playlistVersionModel->saveAll($saveData);
            }

            if (!empty($donePlaylistItemVersionIds)) {
                model(PlaylistItemVersionModel::class)
                    ->where(['id' => ['IN', $donePlaylistItemVersionIds]])->save([
                        'status' => 'review_done',
                        'deal_status' => 'processed'
                    ]);
            }
            if (!empty($notSubmitPlaylistItemVersion)) {
                model(PlaylistItemVersionModel::class)
                    ->where(['id' => ['IN', $notSubmitPlaylistItemVersion]])->save([
                        'status' => 'review_done',
                        'deal_status' => 'no_submit'
                    ]);
            }
        }


        //更新子项的进度
        if (!empty($notDonePlaylistVersionIds)) {
            $notDonePlaylistItemVersionList = model(PlaylistItemVersionModel::class)->where([
                'playlist_version_id' => ['IN', $notDonePlaylistVersionIds],
                'version_id' => ['NEQ', 0]
            ])->select();
            $notDonePlaylistItemVersionSaveAll = [];
            foreach ($notDonePlaylistItemVersionList as $notDonePlaylistItemVersionListItem) {
                if (array_key_exists($notDonePlaylistItemVersionListItem['playlist_version_id'], $notDonePlaylistVersionCurrentReviewCodeMap)) {
                    $notDonePlaylistItemVersionSaveAll[] = [
                        'id' => $notDonePlaylistItemVersionListItem['id'],
                        'current_review_code' => $notDonePlaylistVersionCurrentReviewCodeMap[$notDonePlaylistItemVersionListItem['playlist_version_id']]
                    ];
                }
            }
            if (!empty($notDonePlaylistItemVersionSaveAll)) {
                model(PlaylistItemVersionModel::class)->saveAll($notDonePlaylistItemVersionSaveAll);
            }

        }
        if (!empty($donePlaylistVersionIds)) {
            $donePlaylistItemVersionList = model(PlaylistItemVersionModel::class)->where([
                'playlist_version_id' => ['IN', $donePlaylistVersionIds]
            ])->select();

            $donePlaylistItemVersionSaveAll = [];
            foreach ($donePlaylistItemVersionList as $donePlaylistItemVersionListItem) {
                if (array_key_exists($donePlaylistItemVersionListItem['playlist_version_id'], $donePlaylistVersionCurrentReviewCodeMap)) {
                    $donePlaylistItemVersionSaveAll[] = [
                        'id' => $donePlaylistItemVersionListItem['id'],
                        'current_review_code' => $donePlaylistVersionCurrentReviewCodeMap[$donePlaylistItemVersionListItem['playlist_version_id']]
                    ];
                }
            }
            if (!empty($donePlaylistItemVersionSaveAll)) {
                model(PlaylistItemVersionModel::class)->saveAll($donePlaylistItemVersionSaveAll);
            }
        }


        return [
            'doneSaveData' => count($saveData),
            'notDoneSaveData' => count($notDonePlaylistVersionSaveData)
        ];
    }

    ////异常管理 ======================

    /**
     * 获取延期资产任务查询
     * @param $param
     * @param $currentTenantId
     * @return array
     * @throws \Exception
     */
    public function getDeferredTaskSelect($param, $currentTenantId)
    {
        /**
         *  1、 处理组装过滤条件
         */
        $stepCategoryId = $param['filter']['step_category_id'] ?? [];
        $taskWorkOrderService = TaskWorkOrderService::getInstance();
        $module = $taskWorkOrderService->getModuleByStepCategoryId($stepCategoryId);
        $filter = $taskWorkOrderService->parseMultipleEntityTaskFilter($param['filter']);
        $filter['task.step_type'] = 'step';
//        $filter['entity.module_id'] = $module['id'];
        $filter["task.is_assignee"] = "yes";
        $filter["task.plan_end_time"] = ["lt", time()];

        // 获取任务所有默认状态并排除 已完成状态 final
        $statusService = StatusService::getInstance();
        $statusList = $statusService->getTaskDefaultStatusWithExclude(['final']);
        $statusModelList = array_column(model(StatusModel::class)->field('id,code')->select(), 'id', 'code');
        $statusIds = array_column($statusList, 'id');
        $filter["JSON_UNQUOTE(JSON_EXTRACT(task.json, '$.task_status'))"] = ["IN", $statusIds];
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusModelList['closed']];

        // 任务查询数据字段配置
        $taskFiled = ["task.id", "task.entity_id", "initial_episode_code", "executor", "task.executor_tenant_id", "task.tenant_id", "task.name as step_name",
            "task.assignee_producer", "entity.showings_number", "task.plan_end_time", "entity.name as entity_name", "entity.entity_id as entity_entity_id",
            "entity.entity_module_id",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade"
        ];

        //查询出延期任务
        $page = $param['page'] ?? [1, C('default_page_total')];
        $taskData = model(TaskModel::class)
            ->join('entity on entity.id = task.entity_id')
            ->join('module on module.id = entity.module_id')
            ->join("task_work_order on task_work_order.type = 'task_making' and task_work_order.task_id = task.id", "LEFT")
            ->where($filter)
            ->page($page[0], $page[1])
            ->field('task.id')
            ->group('task.id')
            ->select();

        if (!empty($taskData)) {
            // 查询填充任务版本数据
            $taskIds = array_column($taskData, 'id');
            $taskData = model(TaskModel::class)
                ->join("entity on entity.id = task.entity_id")
                ->join("module on module.id = entity.module_id")
                ->where(['task.id' => ['IN', $taskIds]])
                ->field($taskFiled)
                ->select();

            // 遍历任务数据组装后面需要用到的查询条件
            $executorUserIdList = [];
            $outsideSupplierTenantId = [];
            $parentEntityIdList = [];
            $assigneeProducer = [];
            foreach ($taskData as $taskItem) {
                if ($taskItem['executor_tenant_id'] > 0 && $taskItem['executor_tenant_id'] != $currentTenantId) {
                    $outsideSupplierTenantId[$taskItem['executor_tenant_id']] = $taskItem['executor_tenant_id'];
                } else if ($taskItem['executor'] > 0) {
                    $executorUserIdList[$taskItem['executor']] = $taskItem['executor'];
                }

                if ($taskItem['entity_entity_id'] > 0) {
                    $parentEntityIdList[$taskItem['entity_entity_id']] = $taskItem['entity_entity_id'];
                }

                if (!in_array($taskItem['assignee_producer'], $assigneeProducer)) {
                    $assigneeProducer[] = $taskItem['assignee_producer'];
                }
            }

            //查询出最后一个版本
            $taskMaxVersionIdList = model(VersionModel::class)->where([
                'link_id' => ['IN', $taskIds],
                'module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
                'is_deprecate' => 'no',
            ])
                ->field('max(id) as version_id')
                ->group('link_id')
                ->select();

            $versionData = [];
            if (!empty($taskMaxVersionIdList)) {
                $taskMaxVersionIdList = array_column($taskMaxVersionIdList, 'version_id');

                $versionData = model(VersionModel::class)->where([
                    "id" => ["IN", $taskMaxVersionIdList]
                ])->field('number,link_id,id')->select();

                // 以 link_id为 index 索引填充到任务数据集中
                $versionData = array_column($versionData, null, 'link_id');
            }

            // 如果为shot类型则需要查询所属序列数据
            $entityList = $taskWorkOrderService->getEntityListMap($parentEntityIdList);


            //执行人查询
            $supplierRes = TaskService::getInstance()->queryTaskSupplierInfo($currentTenantId, [], array_values($outsideSupplierTenantId), [], array_values($executorUserIdList));

            //用户信息
            $userNameMap = [];
            if (!empty($assigneeProducer)) {
                $userNameMap = model(UserModel::class)->where(['id' => ['IN', $assigneeProducer]])->field('id,name')->select();
                $userNameMap = array_column($userNameMap, 'name', 'id');
            }

            //工单状态
            $taskWorkOrderList = model(TaskWorkOrderModel::class)->where([
                'task_id' => ["IN", $taskIds],
                'type' => 'task_making'
            ])->field('max(id) as id')->group('task_id')->select();

            $taskWorkOrderListIds = array_column($taskWorkOrderList, 'id');

            $taskWorkOrderMap = [];
            $notes = [];
            if (!empty($taskWorkOrderListIds)) {
                $taskWorkOrderList = model(TaskWorkOrderModel::class)->where([
                    'id' => ["IN", $taskWorkOrderListIds]
                ])->field('id,task_id,status')->select();

                $taskWorkOrderMap = array_column($taskWorkOrderList, null, 'task_id');
                $taskWorkOrderId = array_column($taskWorkOrderList, 'id');

                //工单内容
                $notes = $taskWorkOrderService->getProblemDescription($taskWorkOrderId);
            }

            $dataFormatCallback = function ($item) use ($versionData, $taskWorkOrderMap, $supplierRes, $notes, $userNameMap) {
                $item['task_work_order_type'] = 'task_making';
                $item['version_id'] = $versionData[$item['id']]['id'] ?? 0;
                $item['version_number'] = $versionData[$item['id']]['number'] ?? null;
                $item['producer_name'] = $userNameMap[$item['assignee_producer']] ?? "";
                $item['task_work_order_status'] = null;
                $item['text'] = "";
                if (array_key_exists($item['id'], $taskWorkOrderMap)) {
                    $item['task_work_order_status'] = $taskWorkOrderMap[$item['id']]['status'];
                    if (array_key_exists($taskWorkOrderMap[$item['id']]['id'], $notes)) {
                        $item['text'] = $notes[$taskWorkOrderMap[$item['id']]['id']];
                    }
                }

                $item['executor_name'] = "";
                if ($item['executor_tenant_id'] > 0 && $item['executor_tenant_id'] != $item['tenant_id']) {
                    $item['executor_name'] = $supplierRes['outside'][$item['executor_tenant_id']]['name'] ?? "";
                } elseif ($item['executor'] > 0) {
                    $item['executor_name'] = $supplierRes['executor'][$item['executor']]['name'] ?? "";
                }
                return $item;
            };

            $dataFormatCallbackSub = $dataFormatCallback;
            $dataFormatCallback = function ($item) use (&$dataFormatCallbackSub, &$entityList) {
                $item = $dataFormatCallbackSub($item);
                if (isset(Module::$moduleDictData['module_index_by_id'][$item['entity_module_id']]['code'])) {
                    $item[Module::$moduleDictData['module_index_by_id'][$item['entity_module_id']]['code']] = $entityList[$item['entity_entity_id']]['name'] ?? "";
                }

                return $item;
            };

            //处理数据
            return array_map($dataFormatCallback, $taskData);
        } else {
            return [];
        }
    }

    /**
     * 查看当前用户提交的未完成审核列表的任务
     * @param $param
     * @return array|false|mixed|string
     */
    public function getIncompleteReviewTask($param)
    {
        $page = $param['page'] ?? [1, C('default_page_total')];
//        $stepCategoryId = $param['filter']['step_category_id'];
        $taskWorkOrderService = TaskWorkOrderService::getInstance();
        $statusList = array_column(model(StatusModel::class)->field('id,code')->select(), 'id', 'code');
//        $module = $taskWorkOrderService->getModuleByStepCategoryId($stepCategoryId);
        $filter = $taskWorkOrderService->parseMultipleEntityTaskFilter($param['filter']);
        $filter['step_type'] = 'step';
//        $filter['entity.module_id'] = $module['id'];
        $filter["playlist_version.current_review_code"] = ["neq", "done"];
        $filter["playlist_version.plan_end_time"] = ["lt", time()];
        $filter["JSON_UNQUOTE(JSON_EXTRACT(entity.json, CONCAT('$.', module.code, '_status')))"] = ['NEQ', $statusList['closed']];

        $taskField = ["task.id", "task.entity_id", "entity.initial_episode_code", "task.executor", "entity.showings_number", "playlist_version.plan_end_time",
            "entity.name as entity_name", "playlist_item_version.version_id", "playlist_item_version.review_request_id", "task.name as step_name",
            "playlist_version.current_review_code as playlist_version_review_code",
            "playlist_item_version.current_review_code as playlist_item_version_current_review_code",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category",
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade"
        ];

        $playlistVersionIds = $this->playlistVersionModel
            ->join('playlist_item_version on playlist_item_version.playlist_version_id = playlist_version.id')
            ->join('task on task.id = playlist_item_version.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->join('module on module.id = entity.module_id')
            ->join("task_work_order on task_work_order.type = 'task_making' and task_work_order.task_id = task.id", "LEFT")
            ->where($filter)
            ->field('playlist_version.id')
            ->group('playlist_version.id')
            ->select();

        if (empty($playlistVersionIds)) {
            return [];
        }

        $playlistVersionIds = array_column($playlistVersionIds, 'id');

        //如果存在
        $playlistVersionList = $this->playlistVersionModel
            ->join('playlist_item_version on playlist_item_version.playlist_version_id = playlist_version.id')
            ->join('task on task.id = playlist_item_version.task_id')
            ->join('entity on entity.id = task.entity_id')
            ->join('module on module.id = entity.module_id')
            ->where(["playlist_version.id" => ["IN", $playlistVersionIds]])
            ->field($taskField)
            ->page($page[0], $page[1])
            ->select();

        if (!empty($playlistVersionList)) {
            //补充审核节点
            $reviewRequestIds = [];
            $playlistVersionMap = [];
            $taskIds = [];
            $versionIds = [];
            foreach ($playlistVersionList as $playlistVersionItem) {
                $reviewRequestIds[] = $playlistVersionItem['review_request_id'];
                $playlistVersionMap[$playlistVersionItem['review_request_id']] = $playlistVersionItem['playlist_item_version_current_review_code'];
                $taskIds[] = $playlistVersionItem['id'];
                $versionIds[] = $playlistVersionItem['version_id'];

            }

            //补充版本
            $versions = [];
            if (!empty($versionIds)) {
                $versions = model(VersionModel::class)->where(['id' => ['IN', $versionIds]])->field('id,number')->select();
                $versions = array_column($versions, null, 'id');
            }

            //补充工单状态
            $taskWorkOrderIds = model(TaskWorkOrderModel::class)
                ->where(['task_id' => ['IN', $taskIds], 'type' => 'task_making'])
                ->field('max(id) as id')->group('task_id')->select();
            $taskWorkOrders = [];
            if (!empty($taskWorkOrderIds)) {
                $taskWorkOrderIds = array_column($taskWorkOrderIds, 'id');
                $taskWorkOrders = model(TaskWorkOrderModel::class)
                    ->where(['id' => ['IN', $taskWorkOrderIds]])
                    ->field('task_id,status,type')->select();
                $taskWorkOrders = array_column($taskWorkOrders, null, 'task_id');
            }


            $reviewRequestNodeGroup = [];
            if (!empty($reviewRequestIds)) {
                $reviewRequestNode = model(ReviewRequestNodeModel::class)->where([
                    ['review_request_id' => ["IN", $reviewRequestIds]]
                ])->field('id,role_code,review_request_id,parent_id,plan_reviewer,real_reviewer,is_pass,is_reviewed')->select();

                //是否时当前审核点处理
                $reviewUserMap = [];
                $roleCodes = [];
                foreach ($reviewRequestNode as &$reviewRequestNodeItem) {
                    //如果实际完成人不为空,则填计划完成人
                    if (!empty($reviewRequestNodeItem['real_reviewer'])) {
                        $reviewUserMap[$reviewRequestNodeItem['id']] = $reviewRequestNodeItem['real_reviewer'];
                    } else {
                        $reviewUserMap[$reviewRequestNodeItem['id']] = $reviewRequestNodeItem['plan_reviewer'];
                    }
                    if (!in_array($reviewRequestNodeItem['role_code'], $roleCodes)) {
                        $roleCodes[] = $reviewRequestNodeItem['role_code'];
                    }
                }

                //获取角色名字信息
                $roleNames = [];
                if (!empty($roleCodes)) {
                    $roleNames = $this->getRoleName($roleCodes);
                    $roleNames = array_column($roleNames, 'name', 'code');
                }


                //审核人信息
                $reviewUserValues = array_values($reviewUserMap);
                $reviewUser = model(UserModel::class)->where(['id' => ['IN', $reviewUserValues]])->field('id,name')->select();
                $reviewUser = array_column($reviewUser, 'name', 'id');

                $reviewRequestNode = array_map(function ($reviewRequestNodeItem) use ($playlistVersionMap, $reviewUserMap, $reviewUser, &$roleNames) {
                    //补充审核人名字
                    $reviewRequestNodeItem['reviewer_name'] = $reviewUser[$reviewUserMap[$reviewRequestNodeItem['id']]];

                    //当前审核列表上的角色对应
                    if (array_key_exists($reviewRequestNodeItem['review_request_id'], $playlistVersionMap) &&
                        $playlistVersionMap[$reviewRequestNodeItem['review_request_id']] === $reviewRequestNodeItem['role_code']) {
                        $reviewRequestNodeItem['is_current_review_node'] = 'yes';
                    } else {
                        $reviewRequestNodeItem['is_current_review_node'] = 'no';
                    }

                    $reviewRequestNodeItem['role_name'] = $roleNames[$reviewRequestNodeItem['role_code']] ?? "";
                    return $reviewRequestNodeItem;
                }, $reviewRequestNode);

                //需要进行一次组内排序，以防节点排序出错
                $reviewRequestNodeGroup = array_group_by($reviewRequestNode, 'review_request_id');
                foreach ($reviewRequestNodeGroup as $reviewRequestId => $reviewRequestNodeGroupItem) {
                    $reviewRequestNodeGroup[$reviewRequestId] = array_sort_by($reviewRequestNodeGroupItem, 'parent_id');
                }
            }

            foreach ($playlistVersionList as &$playlistVersionListItem) {
                $playlistVersionListItem['task_work_order_type'] = 'task_making';
                //补充进度
                $playlistVersionListItem['schedule'] = [];
                if (array_key_exists($playlistVersionListItem['review_request_id'], $reviewRequestNodeGroup)) {
                    $playlistVersionListItem['schedule'] = $reviewRequestNodeGroup[$playlistVersionListItem['review_request_id']];
                }


                //补充版本
                $playlistVersionListItem['version_number'] = 0;
                if (array_key_exists($playlistVersionListItem['version_id'], $versions)) {
                    $playlistVersionListItem['version_number'] = $versions[$playlistVersionListItem['version_id']]['number'];
                }

                //补充工单状态
                $playlistVersionListItem['task_work_order_status'] = null;
                if (array_key_exists($playlistVersionListItem['id'], $taskWorkOrders)) {
                    $playlistVersionListItem['task_work_order_status'] = $taskWorkOrders[$playlistVersionListItem['id']]['status'];
                }
            }
        }

        return $playlistVersionList;
    }

    /**
     * 获取任务审核进度
     * @param $data
     * @param $tenantId
     * @return array
     * @throws \Exception
     */
    public function getTaskReviewSchedule($data, $tenantId)
    {
        $taskVersionReviewData = $data['task_version_review_data'];
        $taskIdList = array_column($taskVersionReviewData, 'task_id');

        // 查询出提交审核的版本信息
        // 最大版本 已通过组长审核
        // 外包任务 需要判断review_request的租户id为当前租户id 因为外包任务需要审核两次

        $insideTaskMap = $this->conversionInsideIdMap($taskIdList);
        $taskIds = $insideTaskMap['task_ids'];

        $maxVersionFilter = [
            'version.module_id' => Module::$moduleDictData['module_index_by_code']['task']['id'],
            'version.link_id' => ['IN', implode(',', $taskIds)],
            'version.is_deprecate' => 'no',
            'review_request.need_handle' => 'yes',
            'review_request.tenant_id' => $tenantId,
            [
                'review_request.is_reviewed' => 'no',
                'review_request.is_pass' => 'yes',
                '_logic' => 'or',
            ],
        ];

        $maxVersionIdList = $this->versionModel
            ->join('review_request on review_request.link_id = version.id and review_request.module_id = ' . Module::$moduleDictData['module_index_by_code']['version']['id'])
            ->where($maxVersionFilter)
            ->field('version.link_id,max(version.id) as id')->group('version.link_id')->select();

        if (empty($maxVersionIdList)) {
            throw new LogicException('version not exist', ErrorCode::DATA_INVALID);
        }

        $maxVersionIdList = array_column($maxVersionIdList, 'id');
        $versionReviewRequestList = $this->versionModel
            ->join('review_request on version.id = review_request.link_id and review_request.module_id = ' . Module::$moduleDictData['module_index_by_code']['version']['id'])
            ->where(['version.id' => ['IN', $maxVersionIdList], 'review_request.tenant_id' => $tenantId])
            ->field('version.id as version_id,version.link_id as task_id,review_request.id as review_request_id,review_request.is_reviewed,version.project_id')
            ->select();

        $needReviewCount = array_filter($versionReviewRequestList, function ($item) {
            return $item['is_reviewed'] === 'no';
        });
        if (count($needReviewCount) === 0) {
            throw new LogicException('don`t need submit review', ErrorCode::DATA_INVALID);
        }

        //检验审核流节点
        $reviewRequestIds = array_column($versionReviewRequestList, 'review_request_id');
        $reviewRequestNode = $this->reviewRequestNodeModel->where(['review_request_id' => ["IN", $reviewRequestIds]])->field('id,role_code,parent_id,review_request_id')->select();
        $checkRoleCode = $this->getCheckRoleCode();
        $reviewRequestNodeGroup = array_group_by($reviewRequestNode, 'review_request_id');
        $isAllSyncRoleCodes = "";
        $resData = [];

        foreach ($reviewRequestNodeGroup as $groupReviewRequestId => $groupReviewRequestItem) {
            $groupReviewRequestItem = array_sort_by($groupReviewRequestItem, 'parent_id');
            if ($groupReviewRequestItem[0]['role_code'] != $checkRoleCode && count($groupReviewRequestItem) <= 1) {
                throw new LogicException('task do not need ' . $checkRoleCode . ' after role review', ErrorCode::DATA_INVALID);
            }
            //当前审核版本的审核角色
            $roleCodes = array_column($groupReviewRequestItem, 'role_code');
            $resData = $roleCodes;
            $roleCodes = md5(join('_', $roleCodes));
            //判断任务之间的审核节点是否相同
            if (empty($isAllSyncRoleCodes)) {
                $isAllSyncRoleCodes = $roleCodes;
            } elseif ($isAllSyncRoleCodes != $roleCodes) {
                throw new LogicException(' tasks between review request node are not the same', ErrorCode::TASKS_BETWEEN_REVIEW_REQUEST_NODE_ARE_NOT_THE_SAME);
            }
        }

        $roleData = [];
        if (!empty($resData)) {
            $roleNames = $this->getRoleName($resData);
            if (!empty($roleNames)) {
                $roleNames = array_column($roleNames, 'name', 'code');
                //需要重新排序
                foreach ($resData as $resDataItem) {
                    $roleData[] = $roleNames[$resDataItem];
                }
            }
        }

        return $roleData;
    }

    /**
     * 获取角色名字
     * @param $roleCode
     * @return array|mixed
     */
    public function getRoleName($roleCode)
    {
        $selectResult = [];
        if (!empty($roleCode)) {
            $requestData = [
                'param' => [
                    'filter' => [
                        "role.code" => ['-in', join(",", $roleCode)],
                    ],
                ],
            ];
            $selectResult = teamones_request('teamones-im', 'role/select', $requestData);
        }

        if (isset($selectResult['data'])) {
            return $selectResult['data']['rows'] ?? [];
        }

        return [];
    }

    /**
     * 获取任务的最大版本映射
     * @param $taskIds
     * @return array
     */
    public function getMaxVersionMap($taskIds)
    {
        if (empty($taskIds)) {
            return [];
        }
        $maxVersion = $this->versionModel->where([
            'link_id' => ['IN', $taskIds],
            'module_id' => Module::$moduleDictData['module_index_by_code']['task']['id']
        ])->field('max(id) as version_id')->group('link_id')->select();
        $versionMap = [];
        if (!empty($maxVersion)) {
            $maxVersion = array_column($maxVersion, 'version_id');
            $versionMap = $this->versionModel->where([
                'id' => ['IN', $maxVersion],
            ])->field('id,link_id,number,created')->group('link_id')->select();
            $versionMap = array_column($versionMap, null, 'link_id');
        }

        return $versionMap;
    }

    /**
     * 查询审核节点审核检查节点信息
     * @param int $reviewRequestId
     * @param int $reviewRequestNodeId
     * @param int $tenantId
     * @return array
     */
    public function queryReviewTaskVersionCheckList(int $reviewRequestId, int $reviewRequestNodeId, int $tenantId)
    {
        $res = [
            'is_reviewed' => '',
            'version_check_list' => [],
            'review_request_node' => null,
            'review_request' => null,
            'role_list' => [],
        ];
        // 审核申请数据
        $res['review_request'] = $reviewRequest = model(ReviewRequestModel::class)->find($reviewRequestId);
        // 审核节点数据
        $reviewRequestNodeRoleList = model(ReviewRequestNodeModel::class)->where(['review_request_id' => $reviewRequestId])->field('role_code')->select();

        if (!empty($reviewRequestNodeRoleList)) {
            $reviewRequestNodeRoleList = array_column($reviewRequestNodeRoleList, 'role_code');
            $roleFilter = ['param' => ['filter' => [
                'role.code' => ['-in', implode(',', $reviewRequestNodeRoleList)]
            ], 'fields' => 'role.id,role.name,role.code',]];
            $roleListRes = teamones_request('teamones-im', 'role/select', $roleFilter);
            $res['role_list'] = $roleListRes['data']['rows'];
        }
        // 版本数据
        $versionId = $reviewRequest['link_id'];
        $version = model(VersionModel::class)->find($versionId);
        // 版本审核节点数据
        $versionCheckList = model(VersionCheckListModel::class)->where(['version_id' => $versionId])->order('id ASC')->select();
        $versionCheckListIdList = array_column($versionCheckList, 'id');

        // 内部任务审核流配置查询
        $res['review_request_node'] = $reviewRequestNode = model(ReviewRequestNodeModel::class)->find($reviewRequestNodeId);
        $res['is_reviewed'] = $reviewRequestNode['is_reviewed'];
        // 审核结果预设值查询 (已经审核的 显示审核结果, 没有审核过的展示上一个版本审核结果)
        if ($reviewRequestNode['is_reviewed'] === 'yes') {
            if (!empty($reviewRequestNode['param'])) {
                $checkListReviewResult = json_decode($reviewRequestNode['param'], true);
                $checkListReviewResult = array_column($checkListReviewResult, 'is_pass', 'version_check_list_id');
            } else {
                $checkListReviewResult = [];
            }
        } else {
            $latestVersion = model(VersionModel::class)->where(['module_id' => $version['module_id'], 'link_id' => $version['link_id'], 'id' => ['LT', $versionId]])->find();
            if (!empty($latestVersion)) {
                $checkListReviewResult = model(VersionCheckListModel::class)->where(['version_id' => $latestVersion['id']])->select();
                $checkListReviewResult = array_column($checkListReviewResult, 'is_pass', 'id');
            }
        }

        $latestNoteList = [];
        if (!empty($versionCheckListIdList)) {
            // 当前审核节点发送的最后一条反馈查询
            $latestNoteListFilter = [
                'link_id' => $version['link_id'],
                'version_id' => $versionId,
                'version_check_list_id' => ['IN', $versionCheckListIdList],
                'created_by' => $reviewRequestNode['plan_reviewer']
            ];
            $latestNoteIdList = model(NoteModel::class)->where($latestNoteListFilter)->field('max(id) as id')->group('version_check_list_id')->select();
            $latestNoteIdList = array_column($latestNoteIdList, 'id');
            if (!empty($latestNoteIdList)) {
                $noteService = NoteService::getInstance();
                $noteFilter = [
                    'filter' => [
                        'note.id' => ['IN', $latestNoteIdList]
                    ],
                    'fields' => 'note.version_id,note.created,note.version_check_list_id,note.review_param,note.id,note.tenant_id,note.last_updated,note.text,module.id,module.name,module.code,module.type,note.link_id,note_media.thumb,note_media.md5_name,note_media.param,note_media.size,note_media.type,user.id,user.name,user.avatar,user.email'
                ];
                $latestNoteList = $noteService->selectWithUserDetail($noteFilter, $tenantId);
                $latestNoteList = $latestNoteList['rows'];
                foreach ($latestNoteList as &$latestNote) {
                    $latestNote['version_check_list_id'] = $latestNote['note']['version_check_list_id'];
                }
                $latestNoteList = array_column($latestNoteList, null, 'version_check_list_id');
            }
        }

        // 拼接数据
        foreach ($versionCheckList as $versionCheckListItem) {
            $versionCheckListItem['is_reviewed'] = $reviewRequestNode['is_reviewed'];
            if (isset($checkListReviewResult[$versionCheckListItem['id']])) {
                $versionCheckListItem['is_pass'] = $checkListReviewResult[$versionCheckListItem['id']];
            } else {
                if ($reviewRequestNode['is_reviewed'] === 'yes') {
                    $versionCheckListItem['is_pass'] = $reviewRequestNode['is_pass'];
                } else {
                    $versionCheckListItem['is_pass'] = 'yes';
                }
            }
            $versionCheckListItem['latest_note'] = $latestNoteList[$versionCheckListItem['id']] ?? null;
            $res['version_check_list'][] = $versionCheckListItem;
        }
        return $res;
    }

    /**
     * 查询订单审核管理列表
     * @param int $orderId
     * @param array $filter
     * @param array $param
     * @return array|false|mixed|string
     * @throws \Exception
     */
    public function getOrderTaskReviewList(int $orderId, array $filter, array $param)
    {
        $page = $param['page'] ?? [1, C('default_page_total')];

        $order = model(OrderModel::class)->find($orderId);
        $taskWorkOrderService = TaskWorkOrderService::getInstance();
        $module = $taskWorkOrderService->getModuleByStepCategoryId($order['step_category_id']);
        $filter = $this->parseMultipleEntityTaskFilter($filter);
        $filter['order_task_list.order_id'] = $orderId;
        $taskFields = ['task.id', 'task.step_id', 'task.executor', 'task.plan_end_time', 'entity.id as entity_id', 'entity.name as entity_name',
            'entity.initial_episode_code', 'entity.showings_number', 'order_task_list.deal_status', 'task.plan_end_time', 'task.plan_start_time',
            'task.executor_tenant_id', 'task.executor', 'task.tenant_id', 'entity.entity_id as entity_entity_id'];

        if ($module['code'] === 'asset' || $module['code'] === 'design') {
            $taskFields[] = "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category";
            $taskFields[] = "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade";
        }

        $taskList = model(OrderTaskListModel::class)
            ->join('task on task.id = order_task_list.real_task_id')
            ->join("entity on entity.id = task.entity_id")
            ->join("module on module.id = entity.module_id")
            ->where($filter)->field($taskFields)->page(...$page)->select();

        if (count($taskList) > 0) {
            // step
            $stepIdList = array_column($taskList, 'step_id', 'step_id');
            unset($stepIdList[0]);
            $stepMap = [];
            if (count($stepIdList) > 0) {
                $stepMap = model(StepModel::class)->where(['id' => ['IN', array_values($stepIdList)]])->field('id,name,code')->select();
                $stepMap = array_column($stepMap, null, 'id');
            }
            $taskIds = array_column($taskList, 'id');
            // 提交次数
            $versionMap = $this->getMaxVersionMap($taskIds);
            $reviewRequestList = [];
            $reviewFeedbackNodeList = [];
            if (count($versionMap) > 0) {
                $versionIdList = array_column($versionMap, 'id');
                $versionModuleId = Module::$moduleDictData['module_index_by_code']['version']['id'];
                $reviewRequestFieldsList = [
                    'id', 'is_reviewed', 'is_pass', 'link_id as version_id', 'created', 'is_reviewed', 'reviewed', "JSON_UNQUOTE(JSON_EXTRACT(param,'$.review_deny_node_id')) as review_deny_node_id"
                ];
                // 查询甲方审核记录信息
                $reviewRequestList = model(ReviewRequestModel::class)->where(['module_id' => $versionModuleId, 'link_id' => ['IN', $versionIdList], 'tenant_id' => $order['from_tenant_id']])->field($reviewRequestFieldsList)->select();
                if (count($reviewRequestList) > 0) {
                    $reviewRequestList = array_column($reviewRequestList, null, 'version_id');
                    $reviewFeedbackNodeIdList = array_column($reviewRequestList, 'review_deny_node_id', 'review_deny_node_id');
                    $reviewFeedbackNodeIdList = array_filter($reviewFeedbackNodeIdList, function ($item) {
                        return (int)$item > 0;
                    });
                    if (count($reviewFeedbackNodeIdList) > 0) {
                        $reviewFeedbackNodeList = model(ReviewRequestNodeModel::class)->where(['id' => ['IN', $reviewFeedbackNodeIdList]])->select();
                        $reviewFeedbackNodeList = array_column($reviewFeedbackNodeList, null, 'review_request_id');
                    }
                }

            }
            // 父级实体id
            $parentEntityIdList = [];
            foreach ($taskList as $taskItem) {
                if ($taskItem['entity_entity_id'] > 0) {
                    $parentEntityIdList[$taskItem['entity_entity_id']] = $taskItem['entity_entity_id'];
                }
            }
            $sequenceList = [];
            if ($module['code'] === 'shot') {
                // sequence 查询
                $sequenceList = $taskWorkOrderService->getEntityListMap($parentEntityIdList);
            }

            $dataFormatCallback = function ($item) use (&$versionMap, &$reviewRequestList, &$reviewFeedbackNodeList, &$stepMap) {
                $item['version'] = $versionMap[$item['id']] ?? null;
                $item['step'] = $stepMap[$item['step_id']] ?? null;
                $item['version_id'] = $item['version']['id'] ?? 0;
                $item['review_request'] = $reviewRequestList[$item['version_id']] ?? null;
                $item['feedback_node'] = null;
                if (!empty($item['review_request'])) {
                    $item['feedback_node'] = $reviewFeedbackNodeList[$item['review_request']['id']] ?? null;
                }
                return $item;
            };

            if ($module['code'] === 'shot') {
                $dataFormatCallbackSub = $dataFormatCallback;
                $dataFormatCallback = function ($item) use (&$dataFormatCallbackSub, &$sequenceList) {
                    $item = $dataFormatCallbackSub($item);
                    $item['sequence'] = $sequenceList[$item['entity_entity_id']]['name'] ?? "";
                    return $item;
                };
            }
            $taskList = array_map($dataFormatCallback, $taskList);
        }
        return $taskList;
    }

    /**
     * 提交订单任务列表审核
     * @param array $taskIdList
     * @param int $orderId
     * @return array
     * @throws Exception
     * @throws Throwable
     */
    public function submitOrderTaskListReview(array $taskIdList, int $orderId)
    {
        /**
         * 1. 向甲方发起任务审核
         * 2. 更新订单任务列表item deal_status 为已提交(submitted)
         * 3. 更新外包任务对应的源任务的 deal_status 为不可提交(no_submit)
         */

        $order = model(OrderModel::class)->find($orderId);
        $taskWorkOrderService = TaskWorkOrderService::getInstance();
        $module = $taskWorkOrderService->getModuleByStepCategoryId($order['step_category_id']);
        $isShotModule = in_array($module['code'], ['shot', 'sequence']);

        $taskInfoFilter = [
            'otl.order_id' => $orderId,
            'otl.real_task_id' => ['IN', $taskIdList],
        ];
        $taskQueryFields = [
            'otl.id as order_task_list_id',
            'otl.task_id as source_task_id',
            't.id as task_id',
            't.name as task_name',
            'e.initial_episode_code as initial_episode_code',
            'v.id as version_id',
            'otl.deal_status',
            "JSON_UNQUOTE(JSON_EXTRACT(t.json,'$.task_status')) as task_status_id"
        ];
        $statusService = StatusService::getInstance();
        $waitForPartyAReviewStatus = $statusService->getTaskWaitForPartyAReviewStatus();
        $waitForPartyBSubmitReviewStatus = $statusService->getTaskWaitForPartyBSubmitReviewStatus();
        $waitReviewStatusList = [$waitForPartyAReviewStatus['id'], $waitForPartyBSubmitReviewStatus['id']];

        $taskModuleId = Module::$moduleDictData['module_index_by_code']['task']['id'];

        // 查询最后一个版本数据
        $maxVersionIdList = model(VersionModel::class)
            ->where(['module_id' => $taskModuleId, 'link_id' => ['IN', $taskIdList]])
            ->field('max(id) as version_id,link_id')
            ->group('link_id')
            ->select();
        if (empty($maxVersionIdList)) {
            throw new LogicException("missing Version Data", ErrorCode::TASK_VERSION_NOT_FOUND);
        }
        $maxVersionIdList = array_column($maxVersionIdList, 'version_id', 'link_id');
        $taskInfoList = model(OrderTaskListModel::class)
            ->alias('otl')
            ->join('task t on t.id = otl.real_task_id')
            ->join('entity e on e.id = t.entity_id')
            ->join("version v on v.module_id = $taskModuleId and t.id = v.link_id", 'LEFT')
            ->where($taskInfoFilter)
            ->where(['v.id' => ['IN', array_values($maxVersionIdList)]])
            ->field($taskQueryFields)
            ->select();
        if (count($taskInfoList) !== count($taskIdList)) {
            throw new LogicException('task version info not match', ErrorCode::DATA_INVALID);
        }

        $needCreateReviewRequestTaskInfo = [];
        foreach ($taskInfoList as $taskInfo) {
            // 任务状态检查
            if (!in_array($taskInfo['task_status_id'], $waitReviewStatusList)) {
                if (!$isShotModule) {
                    throw new LogicException('task status can`t submit', ErrorCode::DATA_INVALID);
                }
            } elseif ($taskInfo['deal_status'] != 'to_submit') {
                // 订单任务检查
                if (!$isShotModule) {
                    throw new LogicException('task deal_status can`t submit', ErrorCode::DATA_INVALID);
                }
            } else {
                $needCreateReviewRequestTaskInfo[] = $taskInfo;
            }
        }

        if (count($needCreateReviewRequestTaskInfo) === 0) {
            throw new LogicException('don`t have need submit version', ErrorCode::DATA_INVALID);
        }

        // source_task_info 外包任务的源任务查询


        $insideReviewRequestList = model(ReviewRequestModel::class)
            ->where(['link_id' => ['IN', array_column($needCreateReviewRequestTaskInfo, 'version_id')], 'tenant_id' => $order['to_tenant_id']])
            ->select();
        $insideReviewRequestList = array_column($insideReviewRequestList, null, 'link_id');

        // 内部提交检查
        foreach ($needCreateReviewRequestTaskInfo as $taskInfo) {
            $insideReviewRequest = $insideReviewRequestList[$taskInfo['version_id']] ?? null;
            if (empty($insideReviewRequest)) {
                throw new LogicException($taskInfo['task_name'] . ' inside is not reviewed', ErrorCode::DATA_INVALID);
            }
        }

        $outsideReviewRequestList = model(ReviewRequestModel::class)
            ->where(['link_id' => ['IN', array_column($needCreateReviewRequestTaskInfo, 'version_id')], 'tenant_id' => $order['from_tenant_id']])
            ->select();
        $outsideReviewRequestList = array_column($outsideReviewRequestList, null, 'link_id');

        // 外部提交检查
        foreach ($needCreateReviewRequestTaskInfo as $taskInfo) {
            $outsideReviewRequest = $outsideReviewRequestList[$taskInfo['version_id']] ?? null;
            if (!empty($outsideReviewRequest)) {
                throw new LogicException($taskInfo['task_name'] . ' already submited', ErrorCode::DATA_INVALID);
            }
        }

        // 查询审核流信息
        $firstTaskInfo = $needCreateReviewRequestTaskInfo[0];
        $outsideTaskReviewWorkflowService = OutsideTaskReviewWorkflowService::getInstance();
        $reviewData = $outsideTaskReviewWorkflowService->selectReview($firstTaskInfo['task_id'], $orderId);

        $reviewNodeList = $reviewData['matched_data']['reviewers'];
        $reviewers = [];
        foreach ($reviewNodeList as $nodeData) {
            $firstReviewer = array_shift($nodeData['user_info']);
            $reviewers[] = [
                'role_code' => $nodeData['role_code'],
                'user_id' => $firstReviewer['id'],
                'skip' => 0,
            ];
        }
        $versionModuleId = Module::$moduleDictData['module_index_by_code']['version']['id'];
        $res = [];
        $reviewRequestService = ReviewRequestService::getInstance();
        $reviewDataList = [];
        foreach ($needCreateReviewRequestTaskInfo as $taskInfo) {
            $insideReviewRequest = $insideReviewRequestList[$taskInfo['version_id']] ?? null;
            $order['parent_review_request_id'] = $insideReviewRequest['id'];
            $reviewDataList[] = [
                'reviewers' => $reviewers,
                'data' => [
                    'review_workflow_id' => $reviewData['review_workflow']['id'],
                    'name' => "订单影子任务审核{$order['name']}-{$order['number']}-{$taskInfo['task_name']}",
                    'param' => $order,
                    'link_id' => $taskInfo['version_id'],
                    'module_id' => $versionModuleId,
                    'tenant_id' => $order['from_tenant_id']
                ]
            ];
        }
        $orderTaskListUpdateFilter = ['id' => ['IN', array_column($needCreateReviewRequestTaskInfo, 'order_task_list_id')]];
        $orderTaskListUpdateData = [
            'deal_status' => 'submitted',
        ];
        $sourceTaskUpdateFilter = [
            'id' => ['IN', array_column($needCreateReviewRequestTaskInfo, 'source_task_id')]
        ];
        $commonService = CommonService::instance('task');
        $commonService->setCurrentModuleCode("task");

        $this->reviewRequestModel->startTrans();
        try {
            foreach ($reviewDataList as $reviewData) {
                $res['task_review'][] = $reviewRequestService->create($reviewData);
            }
            // 更新订单任务列表的审核状态 为submitted
            $res['order_task_update'] = model(OrderTaskListModel::class)->where($orderTaskListUpdateFilter)->save($orderTaskListUpdateData);
            // 更新source_task的审核状态为不可提交
            $res['source_task_update'] = model(TaskModel::class)->where($sourceTaskUpdateFilter)->save(['deal_status' => 'no_submit']);
            // 更新task为待甲方审核
            foreach ($needCreateReviewRequestTaskInfo as $taskInfo) {
                $res['task_update'][] = model(TaskModel::class)->modifyItem($commonService->dealUpdateCustomField([
                    'id' => $taskInfo['task_id'],
                    'task_status' => $waitForPartyAReviewStatus['id'],
                ], 'task'));
            }
            $this->reviewRequestModel->commit();
            return $res;

        } catch (Throwable $e) {
            $this->reviewRequestModel->rollback();
            throw $e;
        }
    }

    /**
     * 乙方商务接受反馈
     * @param int $reviewRequestNodeId
     * @return bool
     * @throws Exception
     * @throws Throwable
     */
    public function partybAcceptReviewNote(int $reviewRequestNodeId)
    {
        // 乙方接受反馈 那么任务就需要重新做
        $versionModuleId = Module::$moduleDictData['module_index_by_code']['version']['id'];
        $reviewRequestService = ReviewRequestService::getInstance();
        $reviewRequestNode = model(ReviewRequestNodeModel::class)->find($reviewRequestNodeId);
        $versionData = model(VersionModel::class)
            ->join("review_request rr on rr.module_id = $versionModuleId and rr.link_id = version.id")
            ->where(['rr.id' => $reviewRequestNode['review_request_id']])
            ->field('version.*')
            ->find();
        $orderService = OrderService::getInstance();
        $orderTaskListItem = $orderService->getOrderTaskListItemByRealTaskId($versionData['link_id']);
        $this->taskModel->startTrans();
        try {
            $reviewRequestService->waitFeedbackDeal($reviewRequestNode);
            // 接受反馈后 更新order_task_list的状态
            model(ReviewRequestNodeModel::class)->where(['id' => $reviewRequestNodeId])->save(['partyb_feedback_status' => 'accept_feedback']);
            model(OrderTaskListModel::class)->where(['id' => $orderTaskListItem['id']])->save(['deal_status' => 'processed']);
            $this->taskModel->commit();
        } catch (Throwable $e) {
            $this->taskModel->rollback();
            throw $e;
        }
        return true;
    }

    /**
     * 乙方拒绝反馈
     * @param int $reviewRequestNodeId
     * @return bool
     * @throws Exception
     * @throws Throwable
     */
    public function partybDenyReviewNote(int $reviewRequestNodeId)
    {
        /**
         * 乙方拒绝反馈
         * 1. 修改节点审核状态 状态流转到下一个节点
         */
        $versionModuleId = Module::$moduleDictData['module_index_by_code']['version']['id'];
        $reviewRequestNode = model(ReviewRequestNodeModel::class)->find($reviewRequestNodeId);
        $reviewRequest = model(ReviewRequestModel::class)->find($reviewRequestNode['review_request_id']);
        $versionData = model(VersionModel::class)->alias('v')->join("review_request rr on rr.module_id = $versionModuleId and rr.link_id = v.id")->where(['rr.id' => $reviewRequest['id']])->field('v.*')->find();
        $reviewRequestService = ReviewRequestService::getInstance();
        $orderService = OrderService::getInstance();
        $orderTaskListItem = $orderService->getOrderTaskListItemByRealTaskId($versionData['link_id']);
        $this->taskModel->startTrans();
        try {
            $reviewRequestService->refuseReviewFeedback($reviewRequestNode, $reviewRequest, $versionData['link_id']);
            model(ReviewRequestNodeModel::class)->where(['id' => $reviewRequestNodeId])->save(['partyb_feedback_status' => 'reject_feedback']);
            // 修改订单任务列表item状态
            model(OrderTaskListModel::class)->where(['id' => $orderTaskListItem['id']])->save(['deal_status' => 'submitted']);
            $this->taskModel->commit();
        } catch (Throwable $e) {
            $this->taskModel->rollback();
            throw $e;
        }
        return true;
    }

    /**
     * 获取审核节点及其子节点树
     * @param $param
     * @param int $tenantId
     * @return array
     */
    public function getVersionCheckListTree($param, $tenantId = 0)
    {
        $filter = $param['filter'];
        $version = model(VersionModel::class)
            ->alias('v')
            ->join('task t on t.id = v.link_id')
            ->field('v.id,v.number,v.tenant_id,v.link_id,t.executor_type')
            ->where(['v.id' => $filter['version_id']])
            ->find();
        // 甲方查看
        if (in_array($version['executor_type'], TaskModel::OUTSIDE_EXECUTE_TYPE_GROUP)) {
            $realTask = OrderService::getInstance()->getOutsideTaskByTaskId($version['link_id']);
            if (!empty($realTask)) {
                $version = model(VersionModel::class)
                    ->where([
                        'module_id' => module_by_code('task')['id'],
                        'link_id' => $realTask['id'],
                        'number' => $version['number'],
                    ])
                    ->find();
            }
        }

        $reviewRequestNodeList = model(ReviewRequestNodeModel::class)
            ->join('review_request on review_request.id = review_request_node.review_request_id ')
            ->where(['review_request.link_id' => $version['id'], 'module_id' => Module::$moduleDictData['module_index_by_code']['version']['id']])
            ->field('review_request_node.param,review_request_node.id,plan_reviewer,
            real_reviewer,review_request_node.is_reviewed,review_request_node.is_pass,
            review_request_node.role_code,review_request_node.reviewed,
            review_request_node.is_active,review_request_node.is_second_confirm,review_request_node.partyb_feedback_status,
            review_request_node.is_abolition,
            review_request.tenant_id
            ')
            ->select();

        $reviewRequestNodeList = array_map(function ($reviewRequestNodeItem) use ($version) {
            $reviewRequestNodeItem["is_party_a"] = $reviewRequestNodeItem["tenant_id"] != $version["tenant_id"];
            return $reviewRequestNodeItem;
        }, $reviewRequestNodeList);

        $roleCodes = array_unique(array_column($reviewRequestNodeList, 'role_code'));
        if (!empty($roleCodes)) {
            $roleCodes = $this->getRoleName($roleCodes);
            if (!empty($roleCodes)) {
                $roleCodes = array_column($roleCodes, 'name', 'code');
            }
        }


        $versionCheckList = model(VersionCheckListModel::class)->where([
            'version_id' => $version['id']
        ])->field('version_id,check_list_id,content')->select();

        $reviewRequestNodeUserMap = [];
        $reviewRequestNodeUserValue = [];
        $reviewRequestNodeVersionCheckListIds = [];
        $outsideTenantId = [];
        foreach ($reviewRequestNodeList as $reviewRequestNodeListItem) {
            //获取用户信息,判别审核人
            if (!empty($reviewRequestNodeListItem['real_reviewer'])) {
                $reviewRequestNodeUserMap[$reviewRequestNodeListItem['id']] = $reviewRequestNodeListItem['real_reviewer'];
                $reviewRequestNodeUserValue[] = $reviewRequestNodeListItem['real_reviewer'];
            } else {
                $reviewRequestNodeUserMap[$reviewRequestNodeListItem['id']] = $reviewRequestNodeListItem['plan_reviewer'];
                $reviewRequestNodeUserValue[] = $reviewRequestNodeListItem['plan_reviewer'];
            }

            if ($tenantId != 0 && $tenantId !== $reviewRequestNodeListItem['tenant_id'] && !in_array($reviewRequestNodeListItem['tenant_id'], $outsideTenantId)) {
                $outsideTenantId[] = $reviewRequestNodeListItem['tenant_id'];
            }


            $reviewRequestNodeParam = json_decode($reviewRequestNodeListItem['param'], true);
            if (!empty($reviewRequestNodeParam)) {
                foreach ($reviewRequestNodeParam as $reviewRequestNodeParamItem) {
                    if (!empty($reviewRequestNodeParamItem['version_check_list_id']) && !in_array($reviewRequestNodeParamItem['version_check_list_id'], $reviewRequestNodeVersionCheckListIds)) {
                        $reviewRequestNodeVersionCheckListIds[] = $reviewRequestNodeParamItem['version_check_list_id'];
                    }
                }
            }
        }

        $outsideTenant = [];
        if (!empty($outsideTenantId)) {
            $outsideTenantId = array_unique($outsideTenantId);
            $tenantService = TenantService::getInstance();
            $outsideTenantFilter = [
                "param" => [
                    "filter" => [
                        "tenant.id" => ["-in", implode(',', $outsideTenantId)]
                    ],
                    "fields" => "id,name"
                ]
            ];
            $outsideTenant = $tenantService->tenantSelect($outsideTenantFilter);
            $outsideTenant = array_column($outsideTenant, null, 'id');
        }


        $userList = [];
        if (!empty($reviewRequestNodeUserValue)) {
            $userList = model(UserModel::class)->where(['id' => ['IN', $reviewRequestNodeUserValue]])->field('id,name,avatar,union_id')->select();
            $userList = array_column($userList, null, 'id');
        }

        $checkList = [];
        if (!empty($reviewRequestNodeVersionCheckListIds)) {
            $checkList = model(VersionCheckListModel::class)->where(['id' => ['IN', $reviewRequestNodeVersionCheckListIds]])->field('id,content')->select();
            $checkList = array_column($checkList, 'content', 'id');
        }

        // 内部任务审核流配置查询
        $insideReviewWorkflowService = InsideTaskReviewWorkflowService::getInstance();
        $taskData = model(EntityModel::class)
            ->join('task on task.entity_id = entity.id')->field('task.id,task.step_id,entity.step_workflow_id,entity.project_id')
            ->where(['task.id' => $version['link_id']])->find();

        $checkListConfig = $insideReviewWorkflowService->getTaskCheckListConfig($taskData['id'], $taskData['project_id'], $taskData['step_workflow_id'], $taskData['step_id']);
        $checkListConfig = array_column($checkListConfig, null, 'id');
        foreach ($reviewRequestNodeList as &$reviewRequestNodeListItem) {
            $isParamShow = false;
            $reviewRequestNodeListItem['user'] = [];
            if (array_key_exists($reviewRequestNodeListItem['id'], $reviewRequestNodeUserMap)) {
                if (array_key_exists($reviewRequestNodeUserMap[$reviewRequestNodeListItem['id']], $userList)) {
                    $reviewRequestNodeListItem['user'] = $userList[$reviewRequestNodeUserMap[$reviewRequestNodeListItem['id']]];
                }
            }

            $reviewRequestNodeListItem['outside_tenant'] = null;
            if (array_key_exists($reviewRequestNodeListItem['tenant_id'], $outsideTenant)) {
                $reviewRequestNodeListItem['outside_tenant'] = $outsideTenant[$reviewRequestNodeListItem['tenant_id']];
            }

            //审核状态 reviewing审核中, pass 通过 , failure 不通过 , pending_review 待审核
            $reviewRequestNodeListItem['hurry_up'] = 'no';
            //1.该任务出现在审核人员页面且没有审核 (审核中)
            if ($reviewRequestNodeListItem['is_active'] == 'yes') {
                $reviewRequestNodeListItem['review_status'] = 'reviewing';
                if ($reviewRequestNodeListItem['is_reviewed'] == 'yes') { //审核过没有催一催状态
                    $reviewRequestNodeListItem['hurry_up'] = 'yes';
                }

            } elseif ($reviewRequestNodeListItem['is_reviewed'] == 'yes') {
                if ($reviewRequestNodeListItem['is_second_confirm'] == 'yes') {
                    if ($reviewRequestNodeListItem['is_pass'] == 'yes') {
                        $reviewRequestNodeListItem['review_status'] = 'pass';
                    } else {
                        $reviewRequestNodeListItem['review_status'] = 'failure';
                    }
                } else {

                    //2.该任务审核人员已经审核过,结果为不通过,需要制片处理 (处理中)
                    $reviewRequestNodeListItem['review_status'] = 'reviewing';
                }

            } else {

                //制片提交后的且不在激活状态 (待审核)
                $reviewRequestNodeListItem['review_status'] = 'pending_review';
            }

            $reviewRequestNodeListItem['role_code_name'] = $roleCodes[$reviewRequestNodeListItem['role_code']] ?? '';
            if (!empty($reviewRequestNodeListItem['param'])) {
                $reviewRequestNodeListItem['param'] = json_decode($reviewRequestNodeListItem['param'], true);
                foreach ($reviewRequestNodeListItem['param'] as &$reviewRequestNodeListItemParam) {
                    if (!empty($reviewRequestNodeListItemParam['version_check_list_id']) && !empty($checkList[$reviewRequestNodeListItemParam['version_check_list_id']])) {
                        $reviewRequestNodeListItemParam['content'] = $checkList[$reviewRequestNodeListItemParam['version_check_list_id']];
                    } else {
                        $reviewRequestNodeListItemParam['content'] = "";
                    }
                }
            } else {
                //填充默认数据
                if (!empty($versionCheckList)) {
                    $versionCheckList = array_map(function ($versionCheckListItem) use ($reviewRequestNodeListItem) {
                        $versionCheckListItem['is_reviewed'] = $reviewRequestNodeListItem['is_reviewed'];
                        $versionCheckListItem['is_pass'] = null;
                        // 判断任务是否废除
                        if ($reviewRequestNodeListItem['is_abolition'] == 'yes') {
                            $versionCheckListItem['is_pass'] = 'no';
                        }
                        return $versionCheckListItem;
                    }, $versionCheckList);

                    $versionCheckListMap = array_column($versionCheckList, null, 'check_list_id');
                    if (!empty($checkListConfig)) {
                        $canSeeVersionCheckList = [];
                        foreach ($versionCheckListMap as $checkListId => $versionCheckListItem) {
                            if ((isset($checkListConfig[$checkListId]) && in_array($reviewRequestNodeListItem['role_code'], $checkListConfig[$checkListId]['review_role_config'])) || !isset($checkListConfig[$checkListId])) {
                                $canSeeVersionCheckList[] = $versionCheckListItem;
                            }
                        }
                    } else {
                        $canSeeVersionCheckList = array_values($versionCheckListMap);
                    }
                    $reviewRequestNodeListItem['param'] = $canSeeVersionCheckList;
                }
            }

        }
        return $reviewRequestNodeList;
    }

    /**
     * 修复审核节点二次确认
     * @return bool
     * @throws \Exception
     */
    public function fixReviewRequestNodeIsSecondConfirm()
    {
        // is_second_confirm为新加字段
        // 通过的review_request 的 node节点的二次确认为
        //审核过的review_request 的 审核节点 二次确认都为true
        //没审核完 , 审核节点 审核过 且 为通过状态,二次确认为true
        $reviewRequest = model(ReviewRequestModel::class)
            ->join("review_request_node on review_request_node.review_request_id = review_request.id")
            ->where([
                ['review_request.is_reviewed' => 'yes', 'review_request.module_id' => Module::$moduleDictData['module_index_by_code']['version']['id']],
                ['review_request.is_reviewed' => 'no', 'review_request.module_id' => Module::$moduleDictData['module_index_by_code']['version']['id'],
                    'review_request_node.is_reviewed' => 'yes', 'review_request_node.is_pass' => 'yes'],
                '_logic' => 'or',
            ])->field('review_request_node.id,review_request.is_reviewed')->select();


        $reviewRequestNodeIds = array_column($reviewRequest, 'id');
        $reviewRequestNodeSave = model(ReviewRequestNodeModel::class)->where(['id' => ['IN', $reviewRequestNodeIds]])
            ->save(['is_second_confirm' => 'yes', 'is_active' => 'no']);

        if (empty($reviewRequestNodeSave)) {
            return false;
        }
        return true;
    }

    /**
     * 修复任务的处理状态
     * @return int
     */
    public function fixTaskDealStatus()
    {

        //获取到审核列表中最大版本 ,最大的版本也就是当前任务的版本 ,修改这一批任务的状态
        $playlistItemVersionList = model(PlaylistItemVersionModel::class)->select();
        $versionIds = [];
        foreach ($playlistItemVersionList as $playlistItemVersionListItem) {
            if (!empty($playlistItemVersionListItem['version_id']) && !in_array($playlistItemVersionListItem['version_id'], $versionIds)) {
                $versionIds[] = $playlistItemVersionListItem['version_id'];
            }
        }

        $maxVersion = model(VersionModel::class)->where([
            'id' => ['IN', $versionIds]
        ])
            ->field('link_id,MAX(id) as id')
            ->group('link_id')
            ->select();

        $maxVersionIdMap = array_column($maxVersion, 'id');

        $dealTask = [];
        foreach ($playlistItemVersionList as $playlistItemVersionListItem) {
            if (in_array($playlistItemVersionListItem['version_id'], $maxVersionIdMap)) {
                $dealTask[] = [
                    'id' => $playlistItemVersionListItem['task_id'],
                    'deal_status' => $playlistItemVersionListItem['deal_status']
                ];
            }
        }
        if (!empty($dealTask)) {
            model(TaskModel::class)->saveAll($dealTask);
        }
        return count($dealTask);
    }

    //数据修复顺序 fixReviewRequestNodeIsSecondConfirm ->fixOldCurrentScheduleCodeInPlaylistVersion -> fixCurrentScheduleCodeInPlaylistVersion ->  fixReviewRequestNodeNotReviewList -> fixTaskDealStatus

    /**
     * 修复审核列表子项的租户id
     * @return int
     * @throws \Exception
     */
    public function fixPlaylistItemVersionTenantId()
    {
        $playlistItemVersion = model(PlaylistItemVersionModel::class)->where(['tenant_id' => 0])->select();
        $entityIds = array_column($playlistItemVersion, 'entity_id');
        if (empty($entityIds)) {
            return 0;
        }

        $entity = model(EntityModel::class)->where(['id' => ['IN', $entityIds]])->field('id,tenant_id')->select();
        $entityMap = array_column($entity, 'tenant_id', 'id');

        $savePlaylistItemVersion = [];
        foreach ($playlistItemVersion as $playlistItemVersionItem) {
            if (isset($entityMap[$playlistItemVersionItem['entity_id']])) {
                $savePlaylistItemVersion[$entityMap[$playlistItemVersionItem['entity_id']]][] = $playlistItemVersionItem['id'];
            }
        }
        foreach ($savePlaylistItemVersion as $tenantId => $updateIdList) {
            model(PlaylistItemVersionModel::class)->where(['id' => ['IN', $updateIdList]])->save(['tenant_id' => $tenantId]);
        }

        return count($savePlaylistItemVersion);
    }

    /**
     * 审核管理,提交审核统计 待提交的任务
     * @param $filter
     * @return array
     * @throws \Exception
     */
    public function getTaskSubmitReviewStepCategoryCount($filter)
    {
        $moduleCode = $filter['module_code'];
        $stepCategoryList = StepService::getInstance()->getStepCategoryByMergeModuleConfig($moduleCode, false);
        if (empty($stepCategoryList)) {
            return [];
        }

        $statusData = model(StatusModel::class)->where(["code" => "closed"])->field("id,code")->find();

        $stepCategoryListIds = array_column($stepCategoryList, 'id');

        $taskStepCategoryFilter = [
            'project_id' => $filter['project_id'], 'deal_status' => $filter['deal_status'],
            'step_category_id' => ['IN', $stepCategoryListIds], 'step_type' => 'step',
        ];
        if (!empty($statusData)) {
            $taskStepCategoryFilter["JSON_UNQUOTE(JSON_EXTRACT(json,'$.task_status'))"] = ['NEQ', $statusData['id']];
        }

        $taskStepCategoryCount = model(TaskModel::class)
            ->where($taskStepCategoryFilter)
            ->field('step_category_id,COUNT(id) as task_count')->group('step_category_id')->select();


        $taskStepCategoryCount = array_column($taskStepCategoryCount, 'task_count', 'step_category_id');

        foreach ($stepCategoryList as &$stepCategoryListItem) {
            $stepCategoryListItem['task_count'] = $taskStepCategoryCount[$stepCategoryListItem['id']] ?? 0;
        }

        return $stepCategoryList;
    }

    /**
     * 审核进度处理
     * @param $reviewRequestNodeList
     * @param $reviewRequestCurrentCodeMap
     * @return array
     * @throws \Exception
     */
    public function dealReviewSchedule($reviewRequestNodeList, $reviewRequestCurrentCodeMap)
    {
        //查询审核人名称,角色
        $reviewRequestNodeRoleCodes = [];
        $reviewRequestNodePlanReviewer = [];
        foreach ($reviewRequestNodeList as $reviewRequestNodeListItem) {
            $reviewRequestNodeRoleCodes[] = $reviewRequestNodeListItem['role_code'];
            $reviewRequestNodePlanReviewer[] = $reviewRequestNodeListItem['plan_reviewer'];
        }

        $reviewUser = [];
        if (!empty($reviewRequestNodePlanReviewer)) {
            $reviewUser = model(UserModel::class)->where(['id' => ['IN', $reviewRequestNodePlanReviewer]])->field('id,name')->select();
            $reviewUser = array_column($reviewUser, 'name', 'id');
        }

        $roleInfo = [];
        if (!empty($reviewRequestNodeRoleCodes)) {
            $roleInfo = teamones_request('teamones-im', 'role/select', [
                'param' => [
                    'filter' => [
                        "role.code" => ['-in', join(",", $reviewRequestNodeRoleCodes)]
                    ],
                ],
                'fields' => "id,code,name"
            ])['data']['rows'];
            $roleInfo = array_column($roleInfo, 'name', 'code');
        }

        $reviewRequestNodeGroup = array_group_by($reviewRequestNodeList, 'review_request_id');
        foreach ($reviewRequestNodeGroup as $reviewRequestId => $reviewRequestNodeGroupItem) {
            $shortReviewRequestNode = array_sort_by($reviewRequestNodeGroupItem, 'parent_id');
            foreach ($shortReviewRequestNode as &$shortReviewRequestNodeItem) {
                $shortReviewRequestNodeItem['is_current_review_node'] = ($reviewRequestCurrentCodeMap[$reviewRequestId] === $shortReviewRequestNodeItem['role_code'] ? "yes" : "no");
                $shortReviewRequestNodeItem['review_user_name'] = $reviewUser[$shortReviewRequestNodeItem['plan_reviewer']] ?? null;
                $shortReviewRequestNodeItem['role_name'] = $roleInfo[$shortReviewRequestNodeItem['role_code']] ?? null;
                unset($shortReviewRequestNodeItem['parent_id']);
            }

            $reviewRequestNodeGroup[$reviewRequestId] = $shortReviewRequestNode;
        }

        return $reviewRequestNodeGroup;
    }

    /**
     * 查询订单审核管理列表
     * @param int $tenantId
     * @param array $filter
     * @param array $param
     * @return array
     */
    public function getAllOrderTaskReviewList(int $tenantId, array $filter, array $param)
    {
        $page = $param['page'] ?? [1, C('default_page_total')];

        $filter = $this->parseMultipleEntityTaskFilter($filter);
        $filter['order.to_tenant_id'] = $tenantId;
        $taskFields = ['task.id', 'task.step_id', 'task.executor', 'task.plan_end_time', 'entity.id as entity_id', 'entity.name as entity_name',
            'entity.initial_episode_code', 'entity.showings_number', 'order_task_list.deal_status', 'task.plan_end_time', 'task.plan_start_time',
            'task.executor_tenant_id', 'task.executor', 'task.tenant_id', 'entity.entity_id as entity_entity_id',
            "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_category') )) AS category", "JSON_UNQUOTE(JSON_EXTRACT(entity.json,CONCAT('$.',module.`code`,'_grade') )) AS grade",
            "order.from_tenant_id"
        ];

        $taskList = model(OrderModel::class)
            ->join("`order_task_list` on `order`.id= order_task_list.order_id")
            ->join('task on task.id = order_task_list.real_task_id')
            ->join("entity on entity.id = task.entity_id")
            ->join("module on module.id = entity.module_id")
            ->where($filter)->field($taskFields)->page(...$page)->select();

        if (!empty($taskList)) {
            // step
            $stepIdList = [];
            $taskIds = [];
            $taskFromTenantId = [];
            foreach ($taskList as $taskListItem) {
                $stepIdList[$taskListItem['step_id']] = $taskListItem['step_id'];
                $taskIds[] = $taskListItem['id'];
                $taskFromTenantId[$taskListItem['id']] = $taskListItem['from_tenant_id'];
            }
            unset($stepIdList[0]);
            $stepMap = [];
            if (!empty($stepIdList)) {
                $stepMap = model(StepModel::class)->where(['id' => ['IN', array_values($stepIdList)]])->field('id,name,code')->select();
                $stepMap = array_column($stepMap, null, 'id');
            }
            // 提交次数
            $versionMap = $this->getMaxVersionMap($taskIds);
            $reviewRequestList = [];
            $reviewFeedbackNodeList = [];
            if (!empty($versionMap)) {
                $versionFromTenantIdMap = [];
                foreach ($versionMap as $versionMapItem) {
                    if (isset($taskFromTenantId[$versionMapItem['link_id']])) {
                        if (!isset($versionFromTenantIdMap[$taskFromTenantId[$versionMapItem['link_id']]])) {
                            $versionFromTenantIdMap[$taskFromTenantId[$versionMapItem['link_id']]] = [$versionMapItem['id']];
                        } elseif (in_array($versionMapItem['id'], $versionFromTenantIdMap[$taskFromTenantId[$versionMapItem['link_id']]])) {
                            $versionFromTenantIdMap[$taskFromTenantId[$versionMapItem['link_id']]][] = [$versionMapItem['id']];
                        }
                    }
                }

                $versionFromTenantIdFilter = [];
                foreach ($versionFromTenantIdMap as $fromTenantId => $versionIds) {
                    $versionFromTenantIdFilter[] = ['tenant_id' => $fromTenantId, 'link_id' => ['IN', $versionIds]];
                }
                $reviewRequestFieldsList = [
                    'id', 'is_reviewed', 'is_pass', 'link_id as version_id', 'created', 'is_reviewed', 'reviewed', "JSON_UNQUOTE(JSON_EXTRACT(param,'$.review_deny_node_id')) as review_deny_node_id"
                ];
                // 查询甲方审核记录信息

                if (!empty($versionFromTenantIdFilter)) {
                    $versionFromTenantIdFilter["_logic"] = "OR";
                    $reviewRequestList = model(ReviewRequestModel::class)->where([$versionFromTenantIdFilter, 'module_id' => module_by_code('version')['id'], '_logic' => 'AND',])
                        ->field($reviewRequestFieldsList)->select();
                    if (!empty($reviewRequestList)) {
                        $reviewRequestList = array_column($reviewRequestList, null, 'version_id');
                        $reviewFeedbackNodeIdList = array_column($reviewRequestList, 'review_deny_node_id', 'review_deny_node_id');
                        $reviewFeedbackNodeIdList = array_filter($reviewFeedbackNodeIdList, function ($item) {
                            return (int)$item > 0;
                        });
                        if (!empty($reviewFeedbackNodeIdList)) {
                            $reviewFeedbackNodeList = model(ReviewRequestNodeModel::class)->where(['id' => ['IN', $reviewFeedbackNodeIdList]])->select();
                            $reviewFeedbackNodeList = array_column($reviewFeedbackNodeList, null, 'review_request_id');
                        }
                    }
                }
            }
            // 父级实体id
            $parentEntityIdList = [];
            foreach ($taskList as $taskItem) {
                if ($taskItem['entity_entity_id'] > 0) {
                    $parentEntityIdList[$taskItem['entity_entity_id']] = $taskItem['entity_entity_id'];
                }
            }

            $sequenceList = [];
            if (!empty($parentEntityIdList)) {
                $sequenceList = model(EntityModel::class)->join("module on module.id = entity.module_id")
                    ->where(['id' => ['IN', $parentEntityIdList]])->field('id,name,code,module.code as module_code')->select();
                $sequenceList = array_column($sequenceList, null, 'id');
            }

            $dataFormatCallback = function ($item) use (&$versionMap, &$reviewRequestList, &$reviewFeedbackNodeList, &$stepMap, &$sequenceList) {
                $item['version'] = $versionMap[$item['id']] ?? null;
                $item['step'] = $stepMap[$item['step_id']] ?? null;
                $item['version_id'] = $item['version']['id'] ?? 0;
                $item['review_request'] = $reviewRequestList[$item['version_id']] ?? null;
                $item['feedback_node'] = null;
                if (!empty($item['review_request'])) {
                    $item['feedback_node'] = $reviewFeedbackNodeList[$item['review_request']['id']] ?? null;
                }
                if ($item['entity_entity_id'] > 0 && isset($sequenceList[$item['entity_entity_id']])) {
                    $item[$sequenceList[$item['entity_entity_id']]['module_code']] = $sequenceList[$item['entity_entity_id']]['name'] ?? "";
                }
                return $item;
            };
            $taskList = array_map($dataFormatCallback, $taskList);
        }
        return $taskList;
    }

    /**
     * 资产审核任务列表
     * @param int $tenantId 租户id
     * @param int $userId 当前用户id
     * @param array $param 请求参数
     * @param array $filter 筛选条件
     * @param array $page 分页
     * @return array
     * @throws \Exception
     */
	public function assetReviewTaskList(int $tenantId, int $userId, array $param, array $filter, array $page)
    {
		$queryFilter = [];
		$this->parseReviewTaskListFilter($filter, $queryFilter, $userId, $tenantId, true);
		$fields = [
			'module.id', 'module.code', 'module.name', 'entity.id', 'entity.name', 'entity.code', 'entity.director_star', 'entity.json', 'entity.initial_episode_code', 'entity.showings_number',
			'project.id', 'project.name', 'task.id', 'task.name', 'task.code', 'task.step_id', 'task.step_category_id', 'task.tenant_id', 'task.entity_module_id', 'task.plan_end_time',
			'task.executor_tenant_id', 'task.assignee', 'task.executor', 'task.executor_type', 'task.department_id', 'task.json', 'version.id', 'version.tenant_id', 'version.number',
			'version.is_pass', 'version.is_publish', 'version.description', 'version.param', 'version.json', 'review_request.id', 'review_request.tenant_id', 'review_request.name',
			'review_request.is_pass', 'review_request.is_reviewed', 'review_request.reviewed', 'review_request_node.id', 'review_request_node.parent_id', 'review_request_node.role_code',
			'review_request_node.plan_reviewer', 'review_request_node.real_reviewer', 'review_request_node.is_active', 'review_request_node.is_reviewed', 'review_request_node.reviewed',
			'review_request_node.is_pass',
		];


        $order = "review_request.id desc";
        if ($filter['module_code'] === 'shot') {
            $order = 'entity.initial_episode_code,entity.showings_number,entity.code';
        }

//        $res['total'] = model(ModuleModel::class)
//            ->join('entity on module.id = entity.module_id')
//            ->join('task on entity.id = task.entity_id')
//            ->join('version on task.id = version.link_id and version.module_id = ' . module_by_code('task')['id'])
//            ->join('review_request on review_request.link_id = version.id and review_request.module_id = ' . module_by_code('version')['id'])
//            ->join('review_request_node on review_request.id = review_request_node.review_request_id')
//            ->where($queryFilter)
//            ->count();
        $res['rows'] = model(ModuleModel::class)
            ->join('entity on module.id = entity.module_id')
            ->join('task on entity.id = task.entity_id')
            ->join('project on project.id = task.project_id')
            ->join('task_member on task_member.task_id = task.id', 'LEFT')
            ->join('version on task.id = version.link_id and version.module_id = ' . module_by_code('task')['id'])
            ->join('review_request on review_request.link_id = version.id and review_request.module_id = ' . module_by_code('version')['id'])
            ->join('review_request_node on review_request.id = review_request_node.review_request_id')
            ->where($queryFilter)
            ->field(build_complex_query_fields($fields, '__'))
            ->page(...$page)
            ->group('review_request.id')
            ->order($order)
            ->select();

        $insideTaskList = [];
        $outsideTaskId = [];
        $executorUserId = [];
        $stepIds = [];
        $tenantIds = [];
        $tenantGroupTaskIds = [];
        $departmentIdMap = [];
        $tenantGroupIds = [];
        $versionMediaIdList = [];
        $reviewRequestIdList = [];
        $taskStatusIdList = [];
        $stepCategoryIdList = [];
        foreach ($res['rows'] as &$row) {
            $row = separate_complex_query_data($row);
            $taskJson = json_decode($row['task']['json'], true);
            unset($row['task']['json']);
            $row['task']['task_status'] = $taskJson['task_status'] ?? null;
            if (!empty($row['task']['task_status'])) {
                $taskStatusIdList[$row['task']['task_status']] = $row['task']['task_status'];
            }
            $row['task']['tenant_group_id'] = $taskJson['tenant_group_id'] ?? null;
            $row['task']['is_dismantle_task'] = $taskJson['is_dismantle_task'] ?? null;
            $row['task']['parent_task_id'] = $taskJson['parent_task_id'] ?? null;
            $row['task']['dismantle_name'] = $taskJson['dismantle_name'] ?? null;
            $row['task']['shot_duration'] = $taskJson['shot_duration'] ?? null;
            $row['task']['task_workload_remain'] = $taskJson['task_workload_remain'] ?? null;
            $entityJson = json_decode($row['entity']['json'], true);
            unset($row['entity']['json']);
            $currentEntityModuleCode = module_by_id($row['task']['entity_module_id'])['code'];
            $row['entity']['grade'] = $entityJson[$currentEntityModuleCode . '_grade'] ?? '';
            $row['entity']['category'] = $entityJson[$currentEntityModuleCode . '_category'] ?? '';
            $row['entity']['entity_status_id'] = $entityJson[$currentEntityModuleCode . '_status'] ?? '';
            $tenantIds[$row['task']['executor_tenant_id']] = $row['task']['executor_tenant_id'];
            $executorUserId[$row['review_request_node']['plan_reviewer']] = $row['review_request_node']['plan_reviewer'];
            $reviewRequestIdList[$row['review_request']['id']] = $row['review_request']['id'];
            $row['version']['param'] = json_decode($row['version']['param'], true);
            $versionJson = json_decode($row['version']['json'], true);
            $row['version']['version_media'] = explode(',', $versionJson['version_media'] ?? '');
            foreach ($row['version']['version_media'] as $versionMediaId) {
                $versionMediaIdList[$versionMediaId] = $versionMediaId;
            }
            if ($row['task']['executor_tenant_id'] > 0 && $row['task']['executor_tenant_id'] != $row['task']['tenant_id']) {
                $outsideTaskId[] = $row['task']['id'];
                if ($row['task']["executor_type"] == "tenant_group") {
                    $tenantGroupTaskIds[$row['task']["id"]] = $row['task']["id"];
                    $tenantGroupIds[$row['task']["tenant_group_id"]] = $row['task']["tenant_group_id"];
                }
            } else {
                $insideTaskList[] = $row['task']['id'];
                if ($row['task']['department_id'] != 0) {
                    $departmentIdMap[$row['task']['department_id']] = $row['task']['department_id'];
                }
            }
            if ($row['task']['executor'] != 0) {
                $executorUserId[$row['task']['executor']] = $row['task']['executor'];
            }
            if ($row['task']['assignee'] != 0) {
                $executorUserId[$row['task']['assignee']] = $row['task']['assignee'];
            }
            if ($row['task']['step_id'] != 0) {
                $stepIds[$row['task']['step_id']] = $row['task']['step_id'];
            }
            if ($row['task']['step_category_id'] != 0) {
                $stepCategoryIdList[$row['task']['step_category_id']] = $row['task']['step_category_id'];
            }
        }
        // 审核进度
        $reviewProgressDict = ReviewRequestService::getInstance()->queryReviewRequestProgressData($reviewRequestIdList);
        $outsideMap = ReviewTaskService::getInstance()->getOutsideMap($insideTaskList, $outsideTaskId);
        $insideTaskIdMap = $outsideMap['a_to_b_map'];
        //通过外包筛选出集团任务,获取子公司的 部门 执行人 分配人
        $tenantGroupTaskIdMap = array_intersect_key($insideTaskIdMap, $tenantGroupTaskIds);
        if (!empty($tenantGroupTaskIdMap)) {
            $tenantGroupTaskIdList = array_values($tenantGroupTaskIdMap);
            $tenantGroupTaskList = model(TaskModel::class)->where(["id" => ["IN", $tenantGroupTaskIdList]])->field("id,assignee,executor,department_id")->select();
            foreach ($tenantGroupTaskList as $tenantGroupTaskItem) {
                if ($tenantGroupTaskItem['assignee'] != 0 && !in_array($tenantGroupTaskItem['assignee'], $executorUserId)) {
                    $executorUserId[] = $tenantGroupTaskItem['assignee'];
                }
                if ($tenantGroupTaskItem['executor'] != 0 && !in_array($tenantGroupTaskItem['executor'], $executorUserId)) {
                    $executorUserId[] = $tenantGroupTaskItem['executor'];
                }
                if ($tenantGroupTaskItem['department_id'] != 0 && !in_array($tenantGroupTaskItem['department_id'], $departmentIdMap)) {
                    $departmentIdMap[] = $tenantGroupTaskItem['department_id'];
                }
            }
        }
        $userInfo = TaskService::getInstance()->queryTaskSupplierInfo($tenantId, [], [], $departmentIdMap, $executorUserId, array_values($tenantIds), $tenantGroupIds);
        if (!empty($userInfo["tenant_group"])) {
            $userInfo["tenant_group"] = array_column($userInfo["tenant_group"], null, 'id');
        }
        // step
        $stepDict = [];
        if (!empty($stepIds)) {
            $stepData = model(StepModel::class)->field('id,name,code,color,can_multiple_submit,need_assemble')->where(['id' => ['IN', join(',', $stepIds)]])->cache(6 * 60)->select();
            $stepDict = array_column($stepData, null, 'id');
        }
        // 版本media
        $mediaDict = MediaService::getInstance()->selectMediaParamMap($versionMediaIdList);
        // 状态
        $statusDict = [];
        if (!empty($taskStatusIdList)) {
            $statusDict = model(StatusModel::class)->where(['id' => ['IN', implode(',', $taskStatusIdList)]])->select();
            $statusDict = array_column($statusDict, null, 'id');
        }
        // 环节
        $stepCategoryDict = [];
        if (!empty($stepCategoryIdList)) {
            $stepCategoryDict = model(StepCategoryModel::class)->where(['id' => ['IN', implode(',', $stepCategoryIdList)]])->select();
            $stepCategoryDict = array_column($stepCategoryDict, null, 'id');
        }
        foreach ($res['rows'] as &$row) {
            // 甲方审核 输出原任务id
//            $row['task']['source_id'] = $outsideMap['b_to_a_map'][$row['task']['id']] ?? $row['task']['id'];
            $row['task']['source_id'] = $row['task']['id'];
            $currentTenant = $row['task']['executor_tenant_id'] > 0 ? $row['task']['executor_tenant_id'] : $row['task']['tenant_id'];
            $row['tenant'] = $userInfo['tenant'][$currentTenant] ?? null;
            $row["tenant_group"] = $userInfo["tenant_group"][$row['task']["tenant_group_id"]] ?? null;
            $row["step"] = $stepDict[$row['task']["step_id"]] ?? null;
            $row["step_category"] = $stepCategoryDict[$row['task']["step_category_id"]] ?? null;
            $row['executor'] = $userInfo['executor'][$row['task']['executor']] ?? null;
            $row['assignee'] = $userInfo['executor'][$row['task']['assignee']] ?? null;
            $row['review_progress'] = $reviewProgressDict[$row['review_request']['id']] ?? [];
            $row['task_status'] = $statusDict[$row['task']['task_status']] ?? null;
            foreach ($row['version']['version_media'] as &$versionMediaId) {
                $versionMediaId = $mediaDict[$versionMediaId] ?? null;
            }
        }
        return $res;
    }

    /**
     * 解析审核列表筛选条件
     * @param $filter
     * @param $queryFilter
     * @param $userId
     * @param $tenantId
     * @param $onlyNeedReviewed
     * @return void
     */
    private function parseReviewTaskListFilter($filter, &$queryFilter, $userId, $tenantId, $onlyNeedReviewed): void
	{
        $closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
        $queryFilter[] = [
            "task.json->>'$.task_status'" => ['NEQ', $closedStatus['id']],
            'task.step_type' => TaskModel::STEP_TYPE_STEP,
        ];
        if (!empty($filter['module_code'])) {
            if ($filter['module_code'] === 'asset') {
                $queryFilter['task.entity_module_id'] = [
					'IN', [module_by_code('design')['id'],
					module_by_code('asset')['id'],
					module_by_code('level')['id']]
				];
            } elseif ($filter['module_code'] === 'shot') {
                $queryFilter['task.entity_module_id'] = module_by_code('shot')['id'];
            }
        }
        if ($onlyNeedReviewed) {
            $queryFilter[] = [
                'review_request.tenant_id' => $tenantId,
                'review_request_node.is_active' => 'yes',
                'review_request_node.is_reviewed' => 'no',
                'review_request_node.plan_reviewer' => $userId,
            ];
        }
        unset($filter['module_code']);
        if (!empty($filter['version.project_id'])) {
            // 检查项目是否是甲方项目 甲方项目需要审核乙方项目的任务
            $project = model(ProjectModel::class)->where(['id' => $filter['version.project_id']])->find();
            if (empty($project)) {
                throw new LogicException("project not found", ErrorCode::PROJECT_NOT_FOUND);
            }
            if ($project['type'] === ProjectModel::TYPE_INSOURCE) {
                $projectIdList = model(ProjectModel::class)
                    ->where([
						'id' => $filter['version.project_id'],
						'belong_project_id' => $filter['version.project_id'],
						'_logic' => 'OR'
					])
                    ->field('id')
                    ->column('id');
                if (empty($projectIdList)) {
                    $queryFilter['version.project_id'] = 0;
                } else {
                    $queryFilter['version.project_id'] = ['IN', implode(',', $projectIdList)];
                }
            } else {
                $queryFilter['version.project_id'] = $project['id'];
            }
            unset($filter['version.project_id']);
        }
        $filter = $this->parseMultipleEntityTaskFilter($filter);
        if (!empty($filter)) {
            $queryFilter[] = $filter;
        }
    }

    /**
     * 资产审核任务列表
     * @param int $tenantId 租户id
     * @param int $userId 当前用户id
     * @param array $filter 筛选条件
     * @return array
     */
    public function reviewTaskListEntityCategoryCount(int $tenantId, int $userId, array $filter): array
	{
        $moduleCode = $filter['module_code'] ?? 'asset';

        $queryFilter = [];
        $this->parseReviewTaskListFilter($filter, $queryFilter, $userId, $tenantId, true);
        $resCount = model(ModuleModel::class)
            ->join('entity on module.id = entity.module_id')
            ->join('task on entity.id = task.entity_id')
            ->join('task_member on task.id = task_member.task_id', 'LEFT')
            ->join('version on task.id = version.link_id and version.module_id = ' . module_by_code('task')['id'])
            ->join('review_request on review_request.link_id = version.id and review_request.module_id = ' . module_by_code('version')['id'])
            ->join('review_request_node on review_request.id = review_request_node.review_request_id')
            ->join('step_category on step_category.id = task.step_category_id')
            ->where($queryFilter)
            ->where(['step_category.is_deprecate' => 'no'])
            ->group('task.step_category_id')
            ->field('step_category.code,count(distinct task.id) as count')
            ->select();
        $resCount = array_column($resCount, 'count', 'code');
        $res = ['total' => 0, 'category_count' => []];
        if ($moduleCode == 'asset') {
            $res['category_count'] = [
                [
                    'name' => '概念',
                    'code' => ['design_entity'],
                    'count' => 0,
                ], [
                    'name' => '模型',
                    'code' => ['model'],
                    'count' => 0,
                ], [
                    'name' => '绑定',
                    'code' => ['rig'],
                    'count' => 0,
                ], [
                    'name' => '引擎设置',
                    'code' => ['engine_set'],
                    'count' => 0,
                ], [
                    'name' => '关卡',
                    'code' => ['level_engine', 'level_light', 'level_efx'],
                    'count' => 0,
                ],
                [
                    'name' => '创意资产',
                    'code' => ['creatives_asset'],
                    'count' => 0,
                ],
                [
                    'name' => '动作资产',
                    'code' => ['motion_asset'],
                    'count' => 0,
                ],
                [
                    'name' => '特效资产',
                    'code' => ['efx_asset'],
                    'count' => 0,
                ],
                [
                    'name' => '灯光资产',
                    'code' => ['light_asset'],
                    'count' => 0,
                ],
            ];
        } else {
            $res['category_count'] = [
                [
                    'name' => '动画',
                    'code' => ['shot_motion'],
                    'count' => 0,
                ], [
                    'name' => '解算',
                    'code' => ['shot_solution'],
                    'count' => 0,
                ], [
                    'name' => '灯光',
                    'code' => ['lighting'],
                    'count' => 0,
                ], [
                    'name' => '特效',
                    'code' => ['efx'],
                    'count' => 0,
                ], [
                    'name' => '渲染',
                    'code' => ['Rendering'],
                    'count' => 0,
                ], [
                    'name' => '合成',
                    'code' => ['comp'],
                    'count' => 0,
                ],
                [
                    'name' => '群集',
                    'code' => ['cluster'],
                    'count' => 0,
                ],
            ];
        }

        foreach ($res['category_count'] as &$resItem) {
            foreach ($resItem['code'] as $code) {
                if (isset($resCount[$code])) {
                    $resItem['count'] += $resCount[$code];
                }
            }
        }
        $res['total'] = array_sum(array_values($resCount));
        return $res;
    }

    /**
     * 资产审核任务列表
     * @param int $tenantId 租户id
     * @param int $userId 当前用户id
     * @param array $param 请求参数
     * @param array $filter 筛选条件
     * @param array $page 分页
     * @return array
     */
    public function shotReviewTaskList(int $tenantId, int $userId, array $param, array $filter, array $page)
    {
        $queryFilter = [];
        $this->parseReviewTaskListFilter($filter, $queryFilter, $userId, $tenantId, false);
		$fields = [
			'module.id', 'module.code', 'module.name', 'entity.id', 'entity.name', 'entity.code', 'entity.director_star', 'entity.json', 'entity.initial_episode_code', 'entity.showings_number',
			'task.id', 'task.name', 'task.code', 'task.step_id', 'task.step_category_id', 'task.tenant_id', 'task.entity_module_id', 'task.plan_end_time', 'task.executor_tenant_id', 'task.assignee',
			'task.executor', 'task.executor_type', 'task.department_id', 'task.json',
		];
		$reviewInfoFields = [
			'version.id', 'version.link_id', 'version.number', 'version.is_pass', 'version.is_publish', 'version.description', 'version.json', 'version.param', 'review_request.id',
			'review_request.name', 'review_request.is_pass', 'review_request.is_reviewed', 'review_request.reviewed', 'review_request_node.id', 'review_request_node.parent_id',
			'review_request_node.role_code', 'review_request_node.plan_reviewer', 'review_request_node.real_reviewer', 'review_request_node.is_active', 'review_request_node.is_reviewed',
			'review_request_node.reviewed', 'review_request_node.is_pass',
		];

        $res['rows'] = model(ModuleModel::class)
            ->join('entity on module.id = entity.module_id')
            ->join('task on entity.id = task.entity_id')
            ->join('task_member on task_member.task_id = task.id', 'LEFT')
            ->where($queryFilter)
            ->field(build_complex_query_fields($fields, '__'))
            ->page(...$page)
            ->order('entity.initial_episode_code,entity.showings_number,entity.code')
            ->group('task.id')
            ->select();


        $insideTaskList = [];
        $outsideTaskId = [];
        $executorUserId = [];
        $stepIds = [];
        $tenantIds = [];
        $tenantGroupTaskIds = [];
        $departmentIdMap = [];
        $tenantGroupIds = [];
        $realTaskIdList = [];
        $taskStatusIdList = [];
        $stepCategoryIdList = [];
        foreach ($res['rows'] as &$row) {
            $row = separate_complex_query_data($row);
            $taskJson = json_decode($row['task']['json'], true);
            unset($row['task']['json']);
            $row['task']['task_status'] = $taskJson['task_status'] ?? null;
            if (!empty($row['task']['task_status'])) {
                $taskStatusIdList[$row['task']['task_status']] = $row['task']['task_status'];
            }
            $row['task']['tenant_group_id'] = $taskJson['tenant_group_id'] ?? null;
            $row['task']['is_dismantle_task'] = $taskJson['is_dismantle_task'] ?? null;
            $row['task']['parent_task_id'] = $taskJson['parent_task_id'] ?? null;
            $row['task']['dismantle_name'] = $taskJson['dismantle_name'] ?? null;
            $row['task']['shot_duration'] = $taskJson['shot_duration'] ?? null;
            $row['task']['task_workload_remain'] = $taskJson['task_workload_remain'] ?? null;
            $entityJson = json_decode($row['entity']['json'], true);
            unset($row['entity']['json']);
            $tenantIds[$row['task']['executor_tenant_id']] = $row['task']['executor_tenant_id'];
            if ($row['task']['executor_tenant_id'] > 0 && $row['task']['executor_tenant_id'] != $row['task']['tenant_id']) {
                $outsideTaskId[] = $row['task']['id'];
                if ($row['task']["executor_type"] == "tenant_group") {
                    $tenantGroupTaskIds[$row['task']["id"]] = $row['task']["id"];
                    $tenantGroupIds[$row['task']["tenant_group_id"]] = $row['task']["tenant_group_id"];
                }
            } else {
                $insideTaskList[$row['task']['id']] = $realTaskIdList[$row['task']['id']] = $row['task']['id'];
                if ($row['task']['department_id'] != 0) {
                    $departmentIdMap[$row['task']['department_id']] = $row['task']['department_id'];
                }
            }
            if ($row['task']['executor'] != 0) {
                $executorUserId[$row['task']['executor']] = $row['task']['executor'];
            }
            if ($row['task']['assignee'] != 0) {
                $executorUserId[$row['task']['assignee']] = $row['task']['assignee'];
            }
            if ($row['task']['step_id'] != 0) {
                $stepIds[$row['task']['step_id']] = $row['task']['step_id'];
            }
            if ($row['task']['step_category_id'] != 0) {
                $stepCategoryIdList[$row['task']['step_category_id']] = $row['task']['step_category_id'];
            }
        }
        $outsideMap = ReviewTaskService::getInstance()->getOutsideMap($insideTaskList, $outsideTaskId);
        $insideTaskIdList = $outsideMap['task_ids'];
        $insideTaskIdMap = $outsideMap['a_to_b_map'];
        //通过外包筛选出集团任务,获取子公司的 部门 执行人 分配人
        $tenantGroupTaskIdMap = array_intersect_key($insideTaskIdMap, $tenantGroupTaskIds);
        if (!empty($tenantGroupTaskIdMap)) {
            $tenantGroupTaskIdList = array_values($tenantGroupTaskIdMap);
            $tenantGroupTaskList = model(TaskModel::class)->where(["id" => ["IN", $tenantGroupTaskIdList]])->field("id,assignee,executor,department_id")->select();
            foreach ($tenantGroupTaskList as $tenantGroupTaskItem) {
                if ($tenantGroupTaskItem['assignee'] != 0 && !in_array($tenantGroupTaskItem['assignee'], $executorUserId)) {
                    $executorUserId[] = $tenantGroupTaskItem['assignee'];
                }
                if ($tenantGroupTaskItem['executor'] != 0 && !in_array($tenantGroupTaskItem['executor'], $executorUserId)) {
                    $executorUserId[] = $tenantGroupTaskItem['executor'];
                }
                if ($tenantGroupTaskItem['department_id'] != 0 && !in_array($tenantGroupTaskItem['department_id'], $departmentIdMap)) {
                    $departmentIdMap[] = $tenantGroupTaskItem['department_id'];
                }
            }
        }
        //版本查询
        $maxVersionIdList = model(VersionModel::class)
            ->where(['link_id' => ['IN', implode(',', $insideTaskIdList)], 'module_id' => module_by_code('task')['id']])
            ->field('max(id) as id,link_id')->group('link_id')
            ->column('id');
        $versionReviewRequestList = [];
        $versionMediaIdList = [];
        $reviewRequestIdList = [];
        if (!empty($maxVersionIdList)) {
            $versionReviewRequestList = model(VersionModel::class)
                ->join('review_request on review_request.link_id = version.id and review_request.module_id = ' . module_by_code('version')['id'])
                ->join("review_request_node on review_request.id = review_request_node.review_request_id and review_request_node.is_active = 'yes'", 'LEFT')
                ->where(['review_request.tenant_id' => $tenantId, 'version.id' => ['IN', $maxVersionIdList]])
                ->field(build_complex_query_fields($reviewInfoFields))
                ->select();
            $versionReviewRequestList = array_column($versionReviewRequestList, null, 'version__link_id');
            foreach ($versionReviewRequestList as &$versionReviewRequestItem) {
                $versionReviewRequestItem = separate_complex_query_data($versionReviewRequestItem);
                $reviewRequestIdList[$versionReviewRequestItem['review_request']['id']] = $versionReviewRequestItem['review_request']['id'];
                $versionReviewRequestItem['version']['param'] = json_decode($versionReviewRequestItem['version']['param'], true);
                $versionJson = json_decode($versionReviewRequestItem['version']['json'], true);
                $versionReviewRequestItem['version']['version_media'] = explode(',', $versionJson['version_media'] ?? '');
                foreach ($versionReviewRequestItem['version']['version_media'] as $versionMediaId) {
                    $versionMediaIdList[$versionMediaId] = $versionMediaId;
                }
            }
        }
        // 审核进度
        $reviewProgressDict = ReviewRequestService::getInstance()->queryReviewRequestProgressData($reviewRequestIdList);
        // 版本media
        $mediaDict = MediaService::getInstance()->selectMediaParamMap($versionMediaIdList);
        // step
        $stepDict = [];
        if (!empty($stepIds)) {
            $stepData = model(StepModel::class)->field('id,name,code,color,can_multiple_submit,need_assemble')
				->where(['id' => ['IN', join(',', $stepIds)]])
				->cache(6 * 60)
				->select();
            $stepDict = array_column($stepData, null, 'id');
        }
        // 状态
        $statusDict = [];
        if (!empty($taskStatusIdList)) {
            $statusDict = model(StatusModel::class)->where(['id' => ['IN', implode(',', $taskStatusIdList)]])->select();
            $statusDict = array_column($statusDict, null, 'id');
        }
        $userInfo = TaskService::getInstance()->queryTaskSupplierInfo($tenantId, [], [], $departmentIdMap, $executorUserId, array_values($tenantIds), $tenantGroupIds);
        // 环节
        $stepCategoryDict = [];
        if (!empty($stepCategoryIdList)) {
            $stepCategoryDict = model(StepCategoryModel::class)->where(['id' => ['IN', implode(',', $stepCategoryIdList)]])->select();
            $stepCategoryDict = array_column($stepCategoryDict, null, 'id');
        }
        foreach ($res['rows'] as &$row) {
            $currentTenant = $row['task']['executor_tenant_id'] > 0 ? $row['task']['executor_tenant_id'] : $row['task']['tenant_id'];
            $row['tenant'] = $userInfo['tenant'][$currentTenant] ?? null;
            $row["tenant_group"] = $userInfo["tenant_group"][$row['task']["tenant_group_id"]] ?? null;
            $row["step"] = $stepDict[$row['task']["step_id"]] ?? null;
            $row["step_category"] = $stepCategoryDict[$row['task']["step_category_id"]] ?? null;
            $row['executor'] = $userInfo['executor'][$row['task']['executor']] ?? null;
            $row['assignee'] = $userInfo['executor'][$row['task']['assignee']] ?? null;
            $row['task_status'] = $statusDict[$row['task']['task_status']] ?? null;
            $taskId = $row['task']['source_id'] = $row['task']['id'];
            if (in_array($row['task']['executor_type'], TaskModel::OUTSIDE_EXECUTE_TYPE_GROUP)) {
                $taskId = $insideTaskIdMap[$row['task']['id']] ?? $taskId;
            }
            $reviewVersionData = $versionReviewRequestList[$taskId] ?? [];
            $row = $row + $reviewVersionData;

            $row['review_progress'] = isset($row['review_request']['id']) ? $reviewProgressDict[$row['review_request']['id']] ?? [] : [];
            if (!empty($row['version']['version_media'])) {
                foreach ($row['version']['version_media'] as &$versionMediaId) {
                    $versionMediaId = $mediaDict[$versionMediaId] ?? null;
                }
            }
        }
        return $res;
    }

	/**
	 * 资产-镜头数据统计
	 * @param  int     $userId
	 * @param  int      $tenantId
	 * @return array
	 */
	public function reviewTaskListCount(int $userId, int $tenantId) : array
	{
		//获取未关闭订单状态
		$closedStatus = StatusService::getInstance()->getTaskDefaultClosedStatus();
		// 组装资产镜头查找条件
		$condition = [
			"review_request.tenant_id" => $tenantId,
			"review_request_node.is_active" => "yes",
			"review_request_node.is_reviewed" => "no",
			"review_request_node.plan_reviewer" => $userId,
			"task.entity_module_id" => [
				"in",[module_by_code('design')['id'],
					module_by_code('asset')['id'],
					module_by_code('level')['id'],
					module_by_code('shot')['id']
				]
			],
			"task.json->>'$.task_status'" => ['NEQ', $closedStatus['id']],
			"task.step_type" => TaskModel::STEP_TYPE_STEP,
		];

		// 组装数据 limit 100 提高查询速度 超过100 前端显示 99+
		$dbQuery = model(ModuleModel::class)
			->field("count( distinct task.id) num ")
			->join("entity on module.id = entity.module_id","left")
			->join("task on entity.id = task.entity_id","left")
			->join("version on task.id = version.link_id and version.module_id = " . module_by_code("task")["id"],"inner")
			->join("review_request on review_request.link_id = version.id and review_request.module_id = " . module_by_code("version")["id"],"inner")
			->join("review_request_node on review_request.id = review_request_node.review_request_id","inner")
			->where($condition)
			->limit(100)
			->select();

		if(empty($dbQuery)){
			return ['num' => 0];
		}
		return ['num' => $dbQuery[0]['num']];
	}

}

